死锁:

同步嵌套同步,而且使用的锁不是同一把锁时就可能出现死锁

class Test implements Runnable
{
private boolean flag;
Test(boolean flag)
{
this.flag = flag;
} public void run()
{
if(flag)
{
while(true)
{
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+"...if locka ");
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..if lockb");
}
}
}
}
else
{
while(true)
{
synchronized(MyLock.lockb)
{
System.out.println(Thread.currentThread().getName()+"..else lockb");
synchronized(MyLock.locka)
{
System.out.println(Thread.currentThread().getName()+".....else locka");
}
}
}
}
}
} class MyLock
{
static Object locka = new Object();
static Object lockb = new Object();
} class DeadLockTest
{
public static void main(String[] args)
{
Thread t1 = new Thread(new Test(true));
Thread t2 = new Thread(new Test(false));
t1.start();
t2.start();
}
}

线程间通讯:

其实就是多线程操作同一个资源,但是操作的动作不同。

例,用多线程操作生成一个人名+性别(男的用英文表示,女的用中文表示),然后打印。

class Res
{
String name;
String sex;
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if (x==0)
{
r.name = "Mike";
r.sex="man";
}
else
{
r.name = "丽丽";
r.sex="女";
}
}
x = (x+1)%2;
}
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
System.out.println(r.name + "..." +r.sex);
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

注意:1,操作的共同资源必须上锁;2,使用的锁在内存中一定要保证是唯一的;

在上个例子中,并不是按照我们期待的那样,生成一个对象然后打印该对象,即输入一个就输出一个,这就需要用到等待-唤醒机制。

等待-唤醒:

wait:

notify:

notifyall:

都使用在同步中,因为要对持有监视器(锁)的线程操作,所以使用在同步中,因为只有同步才具有锁。

为什么这些操作线程的方法,要定义在Object类中呢?以为你这些方法在操作同步中线程时,都必须要表示它们所操作线程持有的锁。只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是任意对象,所以被任意对象调用的方法定义在Object中。

class Res
{
String name;
String sex;
Boolean flag=false;
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
{
try
{
r.wait();//如果flag=ture,说明资源中已经有了生产的对象,那么不再生产了,生产线程就wait
}
catch (Exception e)
{
e.printStackTrace();
}
}
if (x==0)
{
r.name = "Mike";
r.sex="man";
}
else
{
r.name = "丽丽";
r.sex="女";
}
r.flag = true;//改变flag标记
r.notify();//唤醒线程池中的第一个等待线程,只在本程序中就是out
}
x = (x+1)%2; }
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)
{
try
{
r.wait();//如果资源中没有生产对象,那么就没有可以打印的对象,这是输出就wait
}
catch (Exception e)
{
e.printStackTrace();
}
} System.out.println(r.name + "..." +r.sex);
r.flag = false;//改变标记
r.notify();//唤醒线程池中的第一个等待线程,本程序中即in
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

优化代码

class Res
{
private String name;
private String sex;
private Boolean flag=false; public synchronized void set(String name,String sex)
{
if (flag)
{
try
{
this.wait();
}
catch (Exception e)
{
e.printStackTrace();
}
this.name = name;
this.sex = sex;
flag = ture;
this.notify();
} }
public synchronized void out()
{
if (!flag)
{
try
{
this.wait();
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println(name + "..." + sex);
flag = false;
this.notify();
}
}
} class Input implements Runnable
{
private Res r;
Input(Res r)
{
this.r = r;
}
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if (x==0)
{
r.set("Mike","man");
}
else
{
r.set("丽丽","女");
}
}
x = (x+1)%2;
}
}
} class Output implements Runnable
{
private Res r;
Output(Res r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
r.out();
}
}
}
} class ThreadCommunication
{
public static void main(String[] args)
{
Res r = new Res();
Input in = new Input(r);
Output out = new Output(r); Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}

当多个线程操作同一个资源,且同一个操作也有多个线程时,就需要使用while判断标记,并用notifyAll唤醒所有线程。

class FactoryDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Product pro = new Product(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
} class Product implements Runnable
{
private Resource r = new Resource();
Product(Resource r)
{
this.r = r;
}
public void run()
{
while (true)
{
r.set("商品");
}
}
} class Consumer implements Runnable
{
private Resource r = new Resource();
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while (true)
{
r.out();
}
}
} class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name)
{
while (flag)//使用while判断标记,避免线程在判断标记之后醒了不判断标记
{
try
{
this.wait();
}
catch (Exception e)
{
}
}
this.name = name + "--" + count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out()
{
while (!flag)//使用while判断标记,避免线程在判断标记之后醒了不从新判断标记
{
try
{
wait();
}
catch (Exception e)
{
}
}
System.out.println(Thread.currentThread().getName()+"...消费者.................."+this.name);
flag = false;
this.notifyAll();
}
}

但notifyAll唤醒对方线程的同时也把本方的线程唤醒了,这是我们不希望看到的。对于该问题的优化,参见Lock接口

Java:多线程<三>死锁、线程间通讯的更多相关文章

  1. (Java多线程系列三)线程间通讯

    Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...

  2. java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)

    本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: package com.zejian.test; /** * @author ...

  3. Java多线程编程(6)--线程间通信(下)

      因为本文的内容大部分是以生产者/消费者模式来进行讲解和举例的,所以在开始学习本文介绍的几种线程间的通信方式之前,我们先来熟悉一下生产者/消费者模式.   在实际的软件开发过程中,经常会碰到如下场景 ...

  4. Java多线程编程核心技术---线程间通信(一)

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

  5. java多线程三之线程协作与通信实例

    多线程的难点主要就是多线程通信协作这一块了,前面笔记二中提到了常见的同步方法,这里主要是进行实例学习了,今天总结了一下3个实例: 1.银行存款与提款多线程实现,使用Lock锁和条件Condition. ...

  6. Java多线程编程(5)--线程间通信

    一.等待与通知   某些情况下,程序要执行的操作需要满足一定的条件(下文统一将其称之为保护条件)才能执行.在单线程编程中,我们可以使用轮询的方式来实现,即频繁地判断是否满足保护条件,若不满足则继续判断 ...

  7. Java多线程编程核心技术---线程间通信(二)

    通过管道进行线程间通信:字节流 Java提供了各种各样的输入/输出流Stream可以很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据,一个线程发送 ...

  8. java多线程5:线程间的通信

    在多线程系统中,彼此之间的通信协作非常重要,下面来聊聊线程间通信的几种方式. wait/notify 想像一个场景,A.B两个线程操作一个共享List对象,A对List进行add操作,B线程等待Lis ...

  9. java 多线程6(线程的·通讯)

    问题1: 为什么wait() 和 notify()是Object类中的方法,而不是Thread类中的方法呢? 答:因为锁是任意对象的所以要在Object类中,如果在Thread类中锁对象不是任意的了. ...

  10. C++多线程编程(三)线程间通信

    多线程编程之三——线程间通讯 作者:韩耀旭 原文地址:http://www.vckbase.com/document/viewdoc/?id=1707 七.线程间通讯 一般而言,应用程序中的一个次要线 ...

随机推荐

  1. js实现继承的五种方式

    function Parent(firstname) { this.fname=firstname; ; this.sayAge=function() { console.log(this.age); ...

  2. sqlserver中对时间类型的字段转换

    获取当前日期利用 convert 来转换成我们需要的datetime格式. select CONVERT(varchar(12) , getdate(), 112 ) 20040912-------- ...

  3. 十、Java基础---------面向对象之抽象类与接口

    抽象类(abstract)     当编写一个类时,时常会为该类定义一些方法,这些方法的使用用以描述该类的行为方式,那么这些方法都有具体的方法体.但是在某些情况下,某个父类只是知道子类应该包含怎样的方 ...

  4. mongodb备份与恢复

    一.备份:mongodump -d mailaccess -c Mail -q ‘{user:”zhaoxy1@szdep.com”}’ -o /data/dump备份mailaccess datab ...

  5. 提高Oracle的WHERE语句性能一些原则

    索引是表的一个概念部分 , 用来提高检索数据的效率, ORACLE 使用了一个复杂的自平衡 B-tree 结构 . 通常 , 通过索引查询数据比全表扫描要快 . 当 ORACLE 找出执行查询和 Up ...

  6. 前端开发面试题JS2

    21.如何判断一个对象是否属于某个类? 使用instanceof if(a instanceof Person){ alert('yes'); } 22.new操作符具体干了什么呢? (1)创建一个空 ...

  7. 2016年上半年金融类App成绩单,手机银行优势尽显! (转自Analysys易观(ID:enfodesk))

    2016已悄然时过大半,金融各领域经过了开年大战,二季度末尾的6月更是几家欢喜几家愁,其中频繁出现的黑马更是足够让人惊喜.我们基于易观千帆6月移动应用大数据,筛选了百款金融类App为您揭晓TOP100 ...

  8. 【转】运行java -version命令时出现错误及解决

    转载地址:http://blog.sina.com.cn/s/blog_50f21fed01012sf2.html     按照上一篇的步骤配置JAVA_HOME.CLASSPATH和Path三个变量 ...

  9. mac攻略(五) -- 使用brew配置php7开发环境(mac+php+apache+mysql+redis)

    前面介绍过基本的配置,后来我又从网上查找了很多资料,经过不断的摸索,下面做了一个总结,希望能对大家提供些许帮助(Mac版本是sierra)   一.mac系统会自带git,而我们要做的是自己安装git ...

  10. Cheatsheet: 2015 07.01 ~ 07.31

    Java JBoss Drools Tutorial for Beginners Other A Simple File System RebornDB: the Next Generation Di ...