博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程---线程间的通信
阅读量:5238 次
发布时间:2019-06-14

本文共 13636 字,大约阅读时间需要 45 分钟。

1 . wait() 方法使当前执行代码的线程进行等待,将当前线程置入"预执行队列",并且在wait()方法所在处停止执行,直到接到通知或者中断。 在调用wait之前,线程必须获得该对象的对象级别锁,即只能在同步方法或者同步代码块中才能调用wait方法调用wait()方法后当前线程自动释放锁。在从wait()返回之前,线程与其他线程竞争重新获得锁。

2 . notify() 用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则由线程规划器随机选出其中一个呈wait状态的线程对其发出notify, 并使它获取该对象的对象锁,值得注意的是在执行notify方法后当前线程不会马上释放该对象锁,呈wait状态的线程也不能马上获得该对象锁,要等到执行notify方法的线程将线程执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态的线程才可以获取该对象锁。当第一个获得了该对象锁的线程运行完毕之后它会释放掉该对象锁,此时如果对象没有再次使用notify方法,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会阻塞在wait状态,直到这个对象发出一个notify或者notifyAll. notify方法也要在同步方法或者同步代码块中才能调用,线程也必须获得该对象的对象级别锁

3 . 执行完同步代码块就会释放对象的锁;在执行同步代码块的过程中,遇到异常而导致线程终止锁也会被释放;在执行同步代码块的过程中,执行了锁所属对象的wait()方法,这个线程将会释放对象锁,而此线程对象将会进入线程等待池中等待被唤醒。

4.方法join()的作用是等待线程对象被销毁。也就是使所属线程对象x正常执行run()方法中的任务而使当前线程z无限期的阻塞,等待x销毁后再继续执行z后面的代码。

public class Test extends Thread{    @Override    public void run() {        int number = (int)(Math.random()*1000);        System.out.println(Thread.currentThread().getName()+" thread will sleep " + number + "ms");        try {            Thread.sleep(number);        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws InterruptedException {        Test test = new Test();        test.setName("test");        test.start();        test.join();        System.out.println("main thread execute after test thread end");    }}运行结果为:test    thread will sleep 595msmain thread execute after test thread end如果不调用join方法输出结果为:main thread execute after test thread endtest thread will sleep 94ms

 

5 .方法join(long millis)和方法sleep(long millis)都有使线程等待一段时间的作用,但是join方法内部是使用wait方法实现的,所以join方法具有释放锁的特点,而sleep方法不会释放锁

6 . 关键字synchronized和wait(),notify()/notifyAll()方法一起使用可以实现等待/通知机制,类ReentrantLock也可以实现同样的功能,但需要借助Condition对象来完成,Condition对象具有更好的灵活性,使用它可以实现多路通知功能,也就是一个Lock对象里面可以创建多个Condition(即对象监视器)对象实例,线程对象可以注册在指定的Condition中,从而有选择的进行通知,在线程调度上更灵活。而在使用notify()/notifyAll()方法进行通知的时候,被通知的线程却是由JVM随机选择的。

  • 使用synchronized和wait,notify实现等待通知机制
public class WaitNotify1 {    public void waitMethod() {        System.out.println("  wait time begin at " + System.currentTimeMillis() / 1000);        synchronized (this) {            try {                this.wait();            } catch (InterruptedException e) {                e.printStackTrace();            }        }        System.out.println("  wait time   end at " + System.currentTimeMillis() / 1000);    }    public void notifyMethod() {        System.out.println("notify time begin at " + System.currentTimeMillis() / 1000);        synchronized (this) {            this.notify();        }        System.out.println("notify time   end at " + System.currentTimeMillis() / 1000);    }    public static void main(String[] args) throws InterruptedException {        WaitNotify1 wn1 = new WaitNotify1();        // 使用匿名内部类的方式启动两个线程分别调用wn1对象的waitMethod和notifyMethod        new Thread(new Runnable() {            @Override            public void run() {                wn1.waitMethod();            }        }).start();        Thread.sleep(1000);        new Thread(new Runnable() {            @Override            public void run() {                wn1.notifyMethod();            }        }).start();        /**         * 打印结果为:          *   wait time begin at 1493194588          * notify time begin at 1493194589         * notify time   end at 1493194589          *   wait time   end at 1493194589         *          */    }}
  • 使用ReentrantLock和Condition对象实现等待-通知机制
public class WaitNotify2 {    private Lock lock = new ReentrantLock();    private Condition con = lock.newCondition();    public void waitMethod() {        try {            lock.lock();// 获得对象锁            System.out.println("  wait time begin at " + System.currentTimeMillis() / 1000);            con.await();// 线程进入等待            System.out.println("  wait time   end at " + System.currentTimeMillis() / 1000);        } catch (InterruptedException e) {            e.printStackTrace();        } finally {            lock.unlock();        }    }    public void notityMethod(){        try {            lock.lock();            System.out.println("notify time begin at " + System.currentTimeMillis() / 1000);            con.signal();// 唤醒线程            System.out.println("notify time   end at " + System.currentTimeMillis() / 1000);        } finally{            lock.unlock();        }    }    public static void main(String[] args) throws InterruptedException {        WaitNotify2 wn2 = new WaitNotify2();        Thread4 thread = new Thread4(wn2);        thread.start();        Thread.sleep(1000);        wn2.notityMethod();    }    /**     * 打印结果为:      *   wait time begin at 1493194430      * notify time begin at 1493194431     * notify time   end at 1493194431      *   wait time   end at 1493194431     *      */}class Thread4 extends Thread {    private WaitNotify2 wn2;    public Thread4(WaitNotify2 wn2) {        this.wn2 = wn2;    }    @Override    public void run() {        wn2.waitMethod();    }}

 

7 . 生产者-消费者模式:

(1) 使用synchronized与wait,notify实现生产者-消费者模式

public class ProducersAndConsumers1 {    private List
list = new ArrayList<>(); public synchronized void produce() { try { while (list.size() == 1) { System.out.println(Thread.currentThread().getName() + " begin waiting "); this.wait(); System.out.println(Thread.currentThread().getName() + " end waiting "); } list.add("nulo"); this.notifyAll(); System.out.println("produced by " + Thread.currentThread().getName() + ",now size = " + list.size()); } catch (Exception e) { e.printStackTrace(); } } public synchronized String consume() { String value = ""; try { while (list.size() == 0) { System.out.println(Thread.currentThread().getName() + " begin waiting "); this.wait(); System.out.println(Thread.currentThread().getName() + " end waiting "); } value = list.get(0); list.remove(0); this.notifyAll(); System.out.println( "consumed by " + Thread.currentThread().getName() + ",now size = " + list.size()); } catch (Exception e) { e.printStackTrace(); } return value; } public static void main(String[] args) throws InterruptedException { ProducersAndConsumers1 pool = new ProducersAndConsumers1(); // 一生产一消费 new ProducerThread("producer",pool).start(); new ConsumerThread("consumer",pool).start(); /** * 打印结果如下: * consumer begin waiting * producer end waiting * produced by producer,now size = 1 * producer begin waiting * consumer end waiting * consumed by consumer,now size = 0 * consumer begin waiting * producer end waiting * produced by producer,now size = 1 * producer begin waiting * consumer end waiting * consumed by consumer,now size = 0 * consumer begin waiting * */ // 一生产多消费 /*new ProducerThread("producer",pool).start(); new ConsumerThread("consumer1",pool).start(); new ConsumerThread("consumer2",pool).start();*/ // 多生产一消费 /*new ProducerThread("producer1",pool).start(); new ProducerThread("producer2",pool).start(); new ConsumerThread("consumer",pool).start();*/ // 多生产多消费 /*new ProducerThread("producer1",pool).start(); new ProducerThread("producer2",pool).start(); new ConsumerThread("consumer1",pool).start(); new ConsumerThread("consumer2",pool).start();*/ }}/** * * 生产者线程 * * @Description * @author niepei * @date 2017年4月26日 下午4:44:17 * @version V1.3.1 */class ProducerThread extends Thread { private ProducersAndConsumers1 pool; public ProducerThread(String name,ProducersAndConsumers1 pool) { super(name); this.pool = pool; } @Override public void run() { while (true) { pool.produce(); } }}/** * * 消费者线程 * * @Description * @author niepei * @date 2017年4月26日 下午4:44:29 * @version V1.3.1 */class ConsumerThread extends Thread { private ProducersAndConsumers1 pool; public ConsumerThread(String name,ProducersAndConsumers1 pool) { super(name); this.pool = pool; } @Override public void run() { while (true) { pool.consume(); } }}

 

(2) 使用ReentrantLock和Condition对象实现生产者-消费者模式

public class ProducersAndConsumers2 {    private List
list = new ArrayList<>(); private Lock lock = new ReentrantLock(); private Condition con = lock.newCondition(); public void produce(){ try { lock.lock(); while(list.size()==1){ System.out.println(Thread.currentThread().getName() + " begin waiting "); con.await(); System.out.println(Thread.currentThread().getName() + " end waiting "); } list.add("nulo"); con.signalAll(); System.out.println("produced by " + Thread.currentThread().getName() + ",now size = " + list.size()); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } public String consume(){ String value = ""; try { lock.lock(); while(list.size()==0){ System.out.println(Thread.currentThread().getName() + " begin waiting "); con.await(); System.out.println(Thread.currentThread().getName() + " end waiting "); } list.remove(0); con.signalAll(); System.out.println("consumed by " + Thread.currentThread().getName() + ",now size = " + list.size()); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } return value; } public static void main(String[] args) throws InterruptedException { ProducersAndConsumers1 pool = new ProducersAndConsumers1(); // 一生产一消费 new ProducerThread("producer",pool).start(); new ConsumerThread("consumer",pool).start(); /** * 打印结果如下: * consumer begin waiting * producer end waiting * produced by producer,now size = 1 * producer begin waiting * consumer end waiting * consumed by consumer,now size = 0 * consumer begin waiting * producer end waiting * produced by producer,now size = 1 * producer begin waiting * consumer end waiting * consumed by consumer,now size = 0 * consumer begin waiting */ }}/** * * 生产者线程 * * @Description * @author niepei * @date 2017年4月26日 下午4:44:17 * @version V1.3.1 */class ProducerThread extends Thread { private ProducersAndConsumers1 pool; public ProducerThread(String name,ProducersAndConsumers1 pool) { super(name); this.pool = pool; } @Override public void run() { while (true) { pool.produce(); } }}/** * * 消费者线程 * * @Description * @author niepei * @date 2017年4月26日 下午4:44:29 * @version V1.3.1 */class ConsumerThread extends Thread { private ProducersAndConsumers1 pool; public ConsumerThread(String name,ProducersAndConsumers1 pool) { super(name); this.pool = pool; } @Override public void run() { while (true) { pool.consume(); } }}

 

8 . 类ThreadLocal可以使每个线程绑定自己的值,它解决的是变量在各个线程之间的隔离问题,也就是不同线程拥有自己的值,不同线程中的值是可以放入ThreadLocal中保存的

public class UseThreadLocal {    public static ThreadLocal
THREAD_LOCAL = new ThreadLocal<>(); private ThreadLocal
threadLocal = new ThreadLocal<>(); public static void main(String[] args) throws InterruptedException { function1(); /** * 打印结果如下: * THREAD_LOCAL in
is null * THREAD_LOCAL in
is null * THREAD_LOCAL in
is test * THREAD_LOCAL in
is main */ new UseThreadLocal().function2(); /** * 打印结果如下: * threadLocal in
is null * threadLocal in
is null * threadLocal in
is test * threadLocal in
is main */ } public static void function1() throws InterruptedException { System.out.println("THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get()); THREAD_LOCAL.set("main"); Thread a = new Thread("test") { @Override public void run() { System.out.println( "THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get()); THREAD_LOCAL.set("test"); System.out.println( "THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get()); } }; a.start(); a.join(); System.out.println("THREAD_LOCAL in <" + Thread.currentThread().getName() + "> is " + THREAD_LOCAL.get()); } public void function2() throws InterruptedException { System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get()); threadLocal.set("main"); Thread a = new Thread("test") { @Override public void run() { System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get()); threadLocal.set("test"); System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get()); } }; a.start(); a.join(); System.out.println("threadLocal in <" + Thread.currentThread().getName() + "> is " + threadLocal.get()); }}

 

转载于:https://www.cnblogs.com/pepper7/p/7196910.html

你可能感兴趣的文章
MySQL简介
查看>>
设计模式之桥接模式(Bridge)
查看>>
jquery的$(document).ready()和onload的加载顺序
查看>>
Python Web框架Django (五)
查看>>
.net学习之继承、里氏替换原则LSP、虚方法、多态、抽象类、Equals方法、接口、装箱拆箱、字符串------(转)...
查看>>
【codevs1033】 蚯蚓的游戏问题
查看>>
【程序执行原理】
查看>>
python的多行注释
查看>>
连接Oracle需要jar包和javadoc文档的下载
查看>>
UVA 10976 - Fractions Again?!
查看>>
Dreamweaver cc新版本css单行显示
查看>>
【android】安卓的权限提示及版本相关
查看>>
JavaScript可否多线程? 深入理解JavaScript定时机制
查看>>
IOS基础学习
查看>>
PHP 导出 Excell
查看>>
Java基础教程——网络基础知识
查看>>
Kruskal基础最小生成树
查看>>
ubuntu 14.04 安装搜狗拼音输入法
查看>>
浅谈算法和数据结构: 一 栈和队列
查看>>
Java内部类详解
查看>>