不使用等待/通知机制实现线程间通信

使用sleep()结合while(true)死循环来实现多个线程间通信

package Third;

import java.util.ArrayList;
import java.util.List; public class MyList { private List list = new ArrayList(); public void add() {
list.add("高洪岩");
} public int size() {
return list.size();
} }
package Third;

public class ThreadA extends Thread {

    private MyList list;

    public ThreadA(MyList list) {
super();
this.list = list;
} @Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
list.add();
System.out.println("添加了" + (i + 1) + "个元素");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class ThreadB extends Thread {

    private MyList list;

    public ThreadB(MyList list) {
super();
this.list = list;
} @Override
public void run() {
try {
while (true) {
if (list.size() == 5) {
System.out.println("==5了,线程b要退出了!");
throw new InterruptedException();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class Test {

    public static void main(String[] args) {
MyList service = new MyList(); ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }

虽然两个线程实现了通信,但有一个弊端是,线程ThreadB.java不停地通过while语轮询机制来检测某一个条件,这样会浪费CPU资源。

如果轮询的时间间隔小,更浪费cpu资源;如果轮询时间间隔大,有可能会娶不到想要的数据。所以就需要有一种机制来减少CPU的资源浪费,而且还可以实现在多个线程间通信,它就是“”wait/notify“”机制。

什么是等待/通信机制

等待/通知机制的实现

package Third;

public class Test1 {
public static void main(String[] args) {
try {
String newString = new String("");
newString.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

出现异常的原因是没有“”对象监视器“”,也就是没有同步加锁

package Third;

public class Test2 {

    public static void main(String[] args) {
try {
String lock = new String();
System.out.println("syn上面");
synchronized (lock) {
System.out.println("syn第一行");
lock.wait();
System.out.println("wait下的代码!");
}
System.out.println("syn下面的代码");
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

线程不能永远等待下去,那样程序就停止不前,不继续向下运行了。如何使呈现wait状态的线程继续运行?答案是notify()

package Third;

public class MyThread1 extends Thread {
private Object lock; public MyThread1(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
try {
synchronized (lock) {
System.out.println("开始 wait time=" + System.currentTimeMillis());
lock.wait();
System.out.println("结束 wait time=" + System.currentTimeMillis());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package Third;

public class MyThread2 extends Thread {
private Object lock; public MyThread2(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
synchronized (lock) {
System.out.println("开始notify time=" + System.currentTimeMillis());
lock.notify();
System.out.println("结束notify time=" + System.currentTimeMillis());
}
}
}
package Third;

public class MyThread2 extends Thread {
private Object lock; public MyThread2(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
synchronized (lock) {
System.out.println("开始notify time=" + System.currentTimeMillis());
lock.notify();
System.out.println("结束notify time=" + System.currentTimeMillis());
}
}
}

下面实现前面的size()=5的实验

package Third;

import java.util.ArrayList;
import java.util.List; public class MyList { private static List list = new ArrayList(); public static void add() {
list.add("anyString");
} public static int size() {
return list.size();
} }
package Third;

public class ThreadA extends Thread {

    private Object lock;

    public ThreadA(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
try {
synchronized (lock) {
if (MyList.size() != 5) {
System.out.println("wait begin "
+ System.currentTimeMillis());
lock.wait();
System.out.println("wait end "
+ System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class ThreadB extends Thread {
private Object lock; public ThreadB(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
MyList.add();
if (MyList.size() == 5) {
lock.notify();
System.out.println("已发出通知!");
}
System.out.println("添加了" + (i + 1) + "个元素!");
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class Run {

    public static void main(String[] args) {

        try {
Object lock = new Object(); ThreadA a = new ThreadA(lock);
a.start(); Thread.sleep(50); ThreadB b = new ThreadB(lock);
b.start();
} catch (InterruptedException e) {
e.printStackTrace();
} } }

日志信息wait end在最后输出,这也说明notify()执行后并不立即释放锁

方法wait()锁释放与notify()锁不释放

当方法wait()被执行后,锁被自动释放,但执行完notify()方法,锁却不自动释放

package Third;

public class Service {

    public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait()");
lock.wait();
System.out.println(" end wait()");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class ThreadA extends Thread {

    private Object lock;

    public ThreadA(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
Service service = new Service();
service.testMethod(lock);
} }
package Third;

public class ThreadB extends Thread {
private Object lock; public ThreadB(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
Service service = new Service();
service.testMethod(lock);
} }
package Third;

public class Test {

    public static void main(String[] args) {

        Object lock = new Object();

        ThreadA a = new ThreadA(lock);
a.start(); ThreadB b = new ThreadB(lock);
b.start(); } }

下面验证方法notify()被执行后,不释放锁

package Third;

public class Service {

    public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait() ThreadName="
+ Thread.currentThread().getName());
lock.wait();
System.out.println(" end wait() ThreadName="
+ Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} public void synNotifyMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
lock.notify();
Thread.sleep(5000);
System.out.println(" end notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
package Third;

public class ThreadA extends Thread {
private Object lock; public ThreadA(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
Service service = new Service();
service.testMethod(lock);
} }
package Third;

public class NotifyThread extends Thread {
private Object lock; public NotifyThread(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
Service service = new Service();
service.synNotifyMethod(lock);
} }
package Third;

public class synNotifyMethodThread extends Thread {
private Object lock; public synNotifyMethodThread(Object lock) {
super();
this.lock = lock;
} @Override
public void run() {
Service service = new Service();
service.synNotifyMethod(lock);
} }
package Third;

public class Test {

    public static void main(String[] args) throws InterruptedException {

        Object lock = new Object();

        ThreadA a = new ThreadA(lock);
a.start(); NotifyThread notifyThread = new NotifyThread(lock);
notifyThread.start(); synNotifyMethodThread c = new synNotifyMethodThread(lock);
c.start(); } }

《Java多线程编程核心技术》读后感(八)的更多相关文章

  1. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  2. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  3. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  4. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  5. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

  6. 《Java 多线程编程核心技术》- 笔记

    作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...

  7. Thread.currentThread()和this的区别——《Java多线程编程核心技术》

    前言:在阅读<Java多线程编程核心技术>过程中,对书中程序代码Thread.currentThread()与this的区别有点混淆,这里记录下来,加深印象与理解. 具体代码如下: pub ...

  8. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  9. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  10. Java多线程编程核心技术(一)Java多线程技能

    1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...

随机推荐

  1. 基于zookeeper或redis实现分布式锁

    前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...

  2. myql 5.6 安装

    环境: centos 6.5  192.168.9.28  4核4G 虚拟机 一. 安装编译源码所需要的工具和库 [root@localhost ~]# yum -y install gcc gcc- ...

  3. MVC教程--MiniProfiler.EF监控调试MVC和EF的性能

    上一篇谈到mvc中ef输出执行sql日志:来谈用mvc开发项目的调试和性能监控.EF框架自动给我生成sql语句,当我们的程序遇到性能问题的时候我们可以用MiniProfiler.EF来监控调试MVC和 ...

  4. Servlet单例模式(注意)

    package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax ...

  5. wepy项目中使用async await

    https://github.com/Tencent/wepy/wiki/wepy项目中使用async-await

  6. 流畅的python学习笔记:第十三章:重载运算符__add__,__iadd__,__radd__,__mul__,__rmul__,__neg__,__eq__,__invert__,__pos__

    在前面第十章以及第一章的时候介绍了Vector对象的运算符重载.第十三章专门介绍运算符重载.这里我们看几个之前没讲过的运算符__neg__,__pos__,__invert__ class Vecto ...

  7. spring运行步骤

    Spring确实使你能通过最简单可行的解决的方法来解决你的问题. 而这是有有非常大价值的.同一时候他的源码的设计理念也受到非常多程序猿的追捧,简洁,易用.但是从哪着手研究Spring却是非常多新手头疼 ...

  8. SVN支干合并(转载)

    分支用来维护独立的开发支线,在一些阶段,你可能需要将分支上的修改合并到最新版本,或者将最新版本的修改合并到分支. 此操作十分重要,在团队开发中,如果你是SVN 的维护者此环节可以说是必不可少,因为团队 ...

  9. ERR:/usr/local/lib/libcrypto.so.1.0.0: no version information available

    解决方法: locate libssl.so.1.0.0   sudo rm /usr/local/lib/libssl.so.1.0.0   sudo ln -s /lib/x86_64-linux ...

  10. CentOS下配置静态IP

    第一.在VMware中进行配置使用桥接的方式.点击编辑选择虚拟网络编辑器 选择桥接模式,选择桥接到外部的网卡.选择我们主机下的网卡 第二步.配置虚拟机使用桥接模式 第三步:启动虚拟机进入到 /etc/ ...