教程-1演示的最简单的使用线程的方法,线程的使用也会带来一些麻烦,下面来看一些例子,同时学习synchronized关键字的使用。
//信息输出类
public class ShowInfo {
public void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
//线程演示类
public class ThreadTest implements Runnable {
private Thread thread;
private ShowInfo showInfo;
private String info;
public ThreadTest(ShowInfo showInfo, String info) {
this.showInfo = showInfo;
this.info = info;
thread = new Thread(this);
thread.start();
}
@Override public void run() {
try {
showInfo.show(info);
}
catch (InterruptedException e) {}
}
public static void main(String[] args) {
ShowInfo showInfo=new ShowInfo();
new ThreadTest(showInfo,"信息01");
new ThreadTest(showInfo,"信息02");
}
}
执行ThreadTest类看看,是不是信息输出格式乱掉了?结果是这样的:
Start====信息01Start====信息02====End
====End
原因就是两个线程是交替进行的,它们都调用了showInfo这个对象的show方法,大家可以想象:如果showInfo这个类不单单是显示数据,而是修改一个集合,或者数组等等包含数据的对象,那么可能得到了错误的结果。
Vector和ArrayList的区别之一就是ArrayList不保证线程安全,指的就是这种情况,那么怎么解决呢?请修改ShowInfo:
public class ShowInfo {
public synchronized void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
再执行ThreadTest类看看,是不是这样的结果:
Start====信息01====End
Start====信息02====End
现在对了吧,当然同步是会带来性能上面的开销,所以建议用ArrayList替换Vector。而且很可能ShowInfo这个类不是你写的,这个时候要怎么处理呢?请看最终的版本:
public class ShowInfo {
public void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
public class ThreadTest implements Runnable {
private Thread thread;
private ShowInfo showInfo;
private String info;
public ThreadTest(ShowInfo showInfo, String info) {
this.showInfo = showInfo;
this.info = info;
thread = new Thread(this);
thread.start();
}
@Override public void run() {
try {
synchronized(showInfo){
showInfo.show(info);
}
}
catch (InterruptedException e) {}
}
public static void main(String[] args) {
ShowInfo showInfo=new ShowInfo();
new ThreadTest(showInfo,"信息01");
new ThreadTest(showInfo,"信息02");
}
}
结果和第二次的还是一样对吧,使用synchronized(要同步的对象){//执行代码}这样的方法可以是任意对象方法都变成同步的,这是比较完美的处理方法。到此,第二课程也讲完了。
//信息输出类
public class ShowInfo {
public void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
//线程演示类
public class ThreadTest implements Runnable {
private Thread thread;
private ShowInfo showInfo;
private String info;
public ThreadTest(ShowInfo showInfo, String info) {
this.showInfo = showInfo;
this.info = info;
thread = new Thread(this);
thread.start();
}
@Override public void run() {
try {
showInfo.show(info);
}
catch (InterruptedException e) {}
}
public static void main(String[] args) {
ShowInfo showInfo=new ShowInfo();
new ThreadTest(showInfo,"信息01");
new ThreadTest(showInfo,"信息02");
}
}
执行ThreadTest类看看,是不是信息输出格式乱掉了?结果是这样的:
Start====信息01Start====信息02====End
====End
原因就是两个线程是交替进行的,它们都调用了showInfo这个对象的show方法,大家可以想象:如果showInfo这个类不单单是显示数据,而是修改一个集合,或者数组等等包含数据的对象,那么可能得到了错误的结果。
Vector和ArrayList的区别之一就是ArrayList不保证线程安全,指的就是这种情况,那么怎么解决呢?请修改ShowInfo:
public class ShowInfo {
public synchronized void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
再执行ThreadTest类看看,是不是这样的结果:
Start====信息01====End
Start====信息02====End
现在对了吧,当然同步是会带来性能上面的开销,所以建议用ArrayList替换Vector。而且很可能ShowInfo这个类不是你写的,这个时候要怎么处理呢?请看最终的版本:
public class ShowInfo {
public void show(String info) throws InterruptedException {
System.out.print("Start====" + info);
Thread.sleep(1000);
System.out.println("====End");
}
}
public class ThreadTest implements Runnable {
private Thread thread;
private ShowInfo showInfo;
private String info;
public ThreadTest(ShowInfo showInfo, String info) {
this.showInfo = showInfo;
this.info = info;
thread = new Thread(this);
thread.start();
}
@Override public void run() {
try {
synchronized(showInfo){
showInfo.show(info);
}
}
catch (InterruptedException e) {}
}
public static void main(String[] args) {
ShowInfo showInfo=new ShowInfo();
new ThreadTest(showInfo,"信息01");
new ThreadTest(showInfo,"信息02");
}
}
结果和第二次的还是一样对吧,使用synchronized(要同步的对象){//执行代码}这样的方法可以是任意对象方法都变成同步的,这是比较完美的处理方法。到此,第二课程也讲完了。