您好,欢迎访问一九零五行业门户网

Java线程协作的方式有哪些

为什么线程之间需要协作线程之间相互配合,完成某项工作,比如:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程。通过这种模式,生产者和消费者被分离,从而实现了“做什么”(what)和“怎么做”(how)的隔离。简单的办法是让消费者线程不断地循环检查变量是否符合预期,在while循环中设置不满足的条件,如果条件满足则退出while循环,从而完成消费者的工作。这样进行线程之间的协作却存在如下2个问题:
(1)难以确保及时性。
(2)难以降低开销。如果降低睡眠的时间,比如休眠1毫秒,这样消费者能更加迅速地发现条件变化,但是却可能消耗更多的处理器资源,造成了无端的浪费。
介绍java中线程协作的最常见的两种方式:利用object.wait()、object.notify()和使用condition
方法一object中的wait、notify、notifyall方法定义如下
public final native void notify(); public final native void notifyall(); public final native void wait(long timeout) throws interruptedexception;
wait()、notify()和notifyall()方法是本地方法,并且为final方法,无法被重写
调用某个对象的wait()方法能让当前线程阻塞,并且当前线程必须拥有此对象的monitor(即锁)
调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程,如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程
调用notifyall()方法能够唤醒所有正在等待这个对象的monitor的线程
之所以这三个方法声明在object类中是因为每个对象都拥有monitor(即锁)
调用某个对象的wait()方法,当前线程必须拥有这个对象的monitor(即锁),因此调用wait()方法必须在同步块或者同步方法中进行
示例
public class test { public static object object = new object(); public static void main(string[] args) { thread1 thread1 = new thread1(); thread2 thread2 = new thread2(); thread1.start(); try { thread.sleep(200); } catch (interruptedexception e) { e.printstacktrace(); } thread2.start(); } static class thread1 extends thread{ @override public void run() { synchronized (object) { try { object.wait(); } catch (interruptedexception e) { } system.out.println("线程"+thread.currentthread().getname()+"获取到了锁"); } } } static class thread2 extends thread{ @override public void run() { synchronized (object) { object.notify(); system.out.println("线程"+thread.currentthread().getname()+"调用了object.notify()"); } system.out.println("线程"+thread.currentthread().getname()+"释放了锁"); } }}
运行结果
线程thread-1调用了object.notify()
线程thread-1释放了锁
线程thread-0获取到了锁
方法二condition是在java 1.5中才出现的,它用来替代传统的object的wait()、notify()实现线程间的协作,相比使用object的wait()、notify(),使用condition1的await()、signal()这种方式实现线程间协作更加安全和高效
condition是个接口,基本的方法就是await()和signal()方法
condition依赖于lock接口,生成一个condition的基本代码是lock.newcondition()
调用condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
示例
public class test { private int queuesize = 10; private priorityqueue<integer> queue = new priorityqueue<integer>(queuesize); private lock lock = new reentrantlock(); private condition notfull = lock.newcondition(); private condition notempty = lock.newcondition(); public static void main(string[] args) { test test = new test(); producer producer = test.new producer(); consumer consumer = test.new consumer(); producer.start(); consumer.start(); } class consumer extends thread{ @override public void run() { consume(); } private void consume() { while(true){ lock.lock(); try { while(queue.size() == 0){ try { system.out.println("队列空,等待数据"); notempty.await(); } catch (interruptedexception e) { e.printstacktrace(); } } queue.poll(); //每次移走队首元素 notfull.signal(); system.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素"); } finally{ lock.unlock(); } } } } class producer extends thread{ @override public void run() { produce(); } private void produce() { while(true){ lock.lock(); try { while(queue.size() == queuesize){ try { system.out.println("队列满,等待有空余空间"); notfull.await(); } catch (interruptedexception e) { e.printstacktrace(); } } queue.offer(1); //每次插入一个元素 notempty.signal(); system.out.println("向队列取中插入一个元素,队列剩余空间:"+(queuesize-queue.size())); } finally{ lock.unlock(); } } } }}
以上就是java线程协作的方式有哪些的详细内容。
其它类似信息

推荐信息