1.join()方法:等子线程执行完成之后再结束主线程.
例子:
public class MyThread extends Thread{ @Override public void run() { try { int sec= (int) (Math.random()*10000); System.out.println(sec); Thread.sleep(sec); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class Test { public static void main(String[] args) throws InterruptedException { MyThread thread=new MyThread(); thread.start(); thread.join(); System.out.println("我想当thread对象执行完毕后我再执行"); System.out.println("但上面代码中的sleep()中的值写多少呢?"); System.out.println("答案是不能确定"); } /* 我想当thread对象执行完毕后我再执行 但上面代码中的sleep()中的值写多少呢? 答案是不能确定 9488 */ }
我们的目的是先执行子线程再进行打印,解决方法:
public class Test { public static void main(String[] args) throws InterruptedException { MyThread thread=new MyThread(); thread.start(); thread.join(); System.out.println("我想当thread对象执行完毕后我再执行"); } /* 5392 我想当thread对象执行完毕后我再执行 */ }
在join的过程中如果线程被中断,则当前线程出现异常
public class ThreadA extends Thread{ @Override public void run() { for (int i = 0; i < Integer.MAX_VALUE; i++) { String newString=new String(""); Math.random(); } } }
public class ThreadB extends Thread{ @Override public void run() { try { ThreadA a=new ThreadA(); a.start(); a.join(); System.out.println("线程B在end处打印了"); } catch (InterruptedException e) { System.out.println("线程B在catch处打印了"); e.printStackTrace(); } } }
public class ThreadC extends Thread{ private ThreadB threadB; public ThreadC(ThreadB threadB){ super(); this.threadB=threadB; } @Override public void run() { threadB.interrupt(); } }
public class Run { public static void main(String[] args) throws InterruptedException { ThreadB b=new ThreadB(); b.start(); Thread.sleep(5000); ThreadC c=new ThreadC(b); c.start(); } /* java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1258) at java.lang.Thread.join(Thread.java:1332) at mutithreading.ThreadB.run(ThreadB.java:12) 线程B在catch处打印了 */ }
join(long)的使用: 只等long秒.
ps:join()和synchronized()方法的区别:
joind在内部使用wait()方法进行等待,而synchronized关键字是使用"对象监视器"原理
join(long)和sleep(long)的区别
join的功能是使用wait(long)方法来实现的,所以join(long)具有释放锁的特点,sleep不会放锁
2.ThreadLocal的使用:
主要解决的就是每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存放存储每个线程的私有数据.
证明ThreadLocal的隔离性:
public class ThreadLocalExt extends ThreadLocal{ @Override protected Object initialValue() { return new Date().getTime(); } }
public class Tools { public static ThreadLocalExt t1=new ThreadLocalExt(); }
public class ThreadA extends Thread{ @Override public void run() { try { for (int i = 0; i <100 ; i++) { Tools.t1.set("ThreadA"+(i+1)); System.out.println("ThreadA get Value="+Tools.t1.get()); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
public class ThreadB extends Thread{ @Override public void run() { try { for (int i = 0; i <100 ; i++) { Tools.t1.set("ThreadB"+(i+1)); System.out.println("ThreadB get Value="+Tools.t1.get()); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } }
public class Run { public static void main(String[] args) { try { ThreadA a=new ThreadA(); ThreadB b=new ThreadB(); a.start(); b.start(); for (int i = 0; i <100 ; i++) { Tools.t1.set("Main"+(i+1)); System.out.println("Main get value="+Tools.t1.get()); Thread.sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } } /*ThreadA get Value=ThreadA1 Main get value=Main1 ThreadB get Value=ThreadB1 Main get value=Main2 ThreadA get Value=ThreadA2 ThreadB get Value=ThreadB2 */ }
总结:3个线程,每个线程都set并且get到自己的值.