Android小知识-Java多线程相关(线程间通信)下篇
本平台的文章更新会有延迟,大家可以关注微信公众号-顾林海,如果大家想获取最新教程,请关注微信公众号,谢谢!
在一种场景中,比如main线程创建并启动了子线程,子线程需要做耗时操作,如果main线程想等子线程执行完成之后再结束,由于main线程比子线程先执行完,因此main线程获取不到子线程的值。我们看下面这段代码:
public class BeanThread extends Thread{
@Override
public void run() {
super.run();
try {
System.out.println("执行一些耗时操作");
Thread.sleep(3000);
System.out.println("经过3秒执行完");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Client:
public class Client {
public static void main(String[] args) {
BeanThread thread=new BeanThread();
thread.start();
System.out.println("main线程执行完");
}
}
执行结果:
main线程执行完
执行一些耗时操作
经过3秒执行完
那如何使主线程等子线程执行完并获取子线程的相关数据?可以使用join()方法,它的作用是使所属的线程对象正常执行run方法中的任务,而使当前线程进行无限期的阻塞,等待所属线程销毁后再继续执行当前线程后面的代码。比如:
public class Client {
public static void main(String[] args) {
BeanThread thread=new BeanThread();
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程执行完");
}
}
再次执行,结果:
执行一些耗时操作
经过3秒执行完
main线程执行完
可以发现执行join()方法后,使当前main线程阻塞,等待BeanThread线程执行结束后,再执行后面打印语句。
方法join具有使线程排队运行的作用,有些类似同步的运行效果。join与synchronized的区别是:join在内部使用wait()方法进行等待,具有释放锁的特点,而synchronized关键字使用的“对象监视器”原理作为同步。在join过程中,如果当前线程对象被中断,则当前线程出现异常。除了无参join方法外,还有一个有参方法join(long),传入的参数代表设定等待的时间。
变量值的共享可以使用public static变量的形式,所有的线程都使用同一个public static变量。如果想实现每一个线程都有自己的共享变量,可以使用ThreadLocal来实现,ThreadLocal主要解决的就是每个线程绑定自己的值。可以通过get()方法返回每个线程自己的值,默认返回的是null,可以通过继承ThreadLocal实现initialVaule()方法来设置默认值。
public class DefaultThreadLocal extends ThreadLocal {
@Override
protected Object initialValue() {
return "默认值";
}
}
第一个线程:
public class ThreadFirst extends Thread {
@Override
public void run() {
super.run();
try {
for(int i=0;i<5;i++){
Client.DEFAULT_THREAD_LOCAL.set("第一个线程存入="+i);
Thread.sleep(1000);
System.out.println("第一个线程取出的值:"+Client.DEFAULT_THREAD_LOCAL.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
第二个线程:
public class ThreadSecond extends Thread {
@Override
public void run() {
super.run();
try {
for(int i=0;i<5;i++){
Client.DEFAULT_THREAD_LOCAL.set("第二个线程存入="+i);
Thread.sleep(500);
System.out.println("第二个线程取出的值:"+Client.DEFAULT_THREAD_LOCAL.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Client:
public class Client {
public static DefaultThreadLocal DEFAULT_THREAD_LOCAL=new DefaultThreadLocal();
public static void main(String[] args) {
ThreadFirst threadFirst=new ThreadFirst();
ThreadSecond threadSecond=new ThreadSecond();
threadFirst.start();
threadSecond.start();
}
}
打印:
第二个线程取出的值:第二个线程存入=0
第二个线程取出的值:第二个线程存入=1
第一个线程取出的值:第一个线程存入=0
第二个线程取出的值:第二个线程存入=2
第二个线程取出的值:第二个线程存入=3
第一个线程取出的值:第一个线程存入=1
第二个线程取出的值:第二个线程存入=4
第一个线程取出的值:第一个线程存入=2
第一个线程取出的值:第一个线程存入=3
第一个线程取出的值:第一个线程存入=4
通过打印结果,可以看出两个线程存入的变量具有隔离性,不会互相干扰,两个线程都往Client.DEFAULT_THREAD_LOCAL存入值,但每个线程还是能取出属于自己的数据。
