线程状态切换示意图:
变量在内存中的工作过程如下:
wait()方法可以使调用该方法的线程释放共享资源的锁,然后从运行状态退出,进入等待队列,直到被再次唤醒。
notify()方法可以随机唤醒等待队列中等待同一共享资源的“一个线程”,并使该线程退出等待队列,进入可运行状态,也就是notify()方法通知“一个”线程。
notifyAll()方法可以使所有正在等待队列中等待同一共享资源的“全部”线程从等待状态退出,进入可运行状态。
带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒。
在使用管道的时候,要进行如下操作:
inputStream.connect(outputStream);
或
outputStream.connect(inputStream);
join的作用是等待线程对象销毁。主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程往往早于子线程结束之前结束。这时,如果主线程想等待子线程执行完成之后再结束,就用到了join。
public class MyThread extends Thread {
@Override
public void run(){
try{
int secondValue = (int)(Math.random() * 10000);
System.out.println(secondValue);
Thread.sleep(secondValue);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
主线程代码如下:
public class Run17 {
public static void main(String[] args) {
try{
MyThread threadTest = new MyThread();
threadTest.start();
threadTest.join();
System.out.println("我想当threadTest对象执行完毕后我再执行");
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//Output
8196
我想当threadTest对象执行完毕后我再执行
方法join(long)中的参数是设定等待的时间。在程序中,我们将join(long)改为sleep(long),从运行结果来看是相同的,那么这两个方法有什么不同呢?
方法join(long)的功能在内部是使用wait(long)方法来实现的,所以join(long)方法具有释放锁的特点。源码如下:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
从源码可以看到,当执行wait(long)方法时,当前线程的锁被释放,那么其他线程就可以调用此线程中的同步方法了。而Thread.sleep(long)方法却不释放锁。
作用是每个线程绑定自己的值,可以理解为HashMap
使用类InheritableThreadLocal的使用可以让子线程从父线程中取得值。实例代码如下:
public class InheritableThreadLocalExt extends InheritableThreadLocal<String> {
@Override
protected String initialValue() {
return new Date().getTime()+"";
}
@Override
protected String childValue(String parentValue) {
return parentValue + " 我在子线程加的~!";
}
}
public class Tools1 {
public static InheritableThreadLocalExt tl = new InheritableThreadLocalExt();
}
子线程代码如下:
public class ThreadA11 extends Thread {
@Override
public void run(){
try{
for(int i = 0; i < 2; i++){
System.out.println("在ThreadA线程中取值=" + Tools1.tl.get());
Thread.sleep(100);
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
主线程代码如下:
public class Run26 {
public static void main(String[] args) {
try{
for(int i = 0; i < 2; i++){
System.out.println("在Main线程中取值=" + Tools1.tl.get());
Thread.sleep(100);
}
Thread.sleep(5000);
ThreadA11 a = new ThreadA11();
a.start();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//Output
在Main线程中取值=1486978985517
在Main线程中取值=1486978985517
在ThreadA线程中取值=1486978985517 我在子线程加的~!
在ThreadA线程中取值=1486978985517 我在子线程加的~!