黑马程序员---Java多线程(2)

来源:互联网 发布:买票软件哪个好知乎 编辑:程序博客网 时间:2024/04/28 08:37
------- android培训、java培训、期待与您交流! ----------

1.当单例模式遇到多线程

单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。
但是如果在多线程并发执行情况下,可能会出现多个实例的现象,解决办法如下:   
//懒汉式public class Single2 {private static Single2 s = null;private Single2() {}public static Single2 getInstance() {if (s == null) {synchronized (Single2.class) {if (s == null) {s = new Single2();}}}return s;}}
当然对于饿汉式,不存在这个问题;
//饿汉式public class Single {private static final Single s = new Single();private Single(){}public static Single getInstance(){return s;}}

2.多线程间通信(生产者和消费者问题)

如果程序中只有2个线程,一个负责生产,一个负责消费,那么如下就可以解决:
public class Resource {private String name;private String sex;private boolean flag;public synchronized void set(String name, String sex) {if (flag) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}this.name = name;this.sex = sex;flag = true;this.notify();}public synchronized void out() {if (!flag) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(this.name + "  " + this.sex);flag = false;this.notify();}public boolean getFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}}

但是如果有多个生产线程和消费线程的时候,上面的做法就不能正确执行了,还可能会出现死锁的现象。可以采取一下的方式:
public synchronized void set(String name, String sex) {while (flag) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}this.name = name;this.sex = sex;flag = true;this.notifyAll();}public synchronized void out() {while (!flag) {try {this.wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(this.name + "  " + this.sex);flag = false;this.notifyAll();}
采用while防止线程被唤醒后不去判断Flag而直接向下执行, 为了保证一定能唤醒需要的线程,采取notifyAll()方式,将线程池中所有被wait的线程都唤醒

但是这样会带来新的难题,如果每次都把所有被wait的线程唤醒,很影响执行效率。

为此在JDK1.5以后,有了新的处理方式:

接口 Lock

Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的
Condition对象。

ConditionObject 监视器方法(waitnotifynotifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待 

set(wait-set)。其中,Lock 替代了synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。  

使用也十分方便,可以改成如下:

public class Res {private String name;private int count = 1;private boolean flag = false;private Lock lock = new ReentrantLock();private Condition pro_con = lock.newCondition();private Condition cum_con = lock.newCondition();public void set(String name) {lock.lock();try {while (flag) {try {pro_con.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}this.name = name + count;count++;System.out.println(Thread.currentThread().getName() + "produce"+ this.name);flag = true;cum_con.signal();} catch (Exception e) {// TODO: handle exception} finally {lock.unlock();}}public  void out() {lock.lock();try {while (!flag) {try {cum_con.await();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(Thread.currentThread().getName() + "consume"+ this.name);flag = false;pro_con.signal();} catch (Exception e) {// TODO: handle exception} finally {lock.unlock();}}}

在查看JDK时候看到下面代码,对数组的多线程处理,很有思路

class BoundedBuffer {   final Lock lock = new ReentrantLock();   final Condition notFull  = lock.newCondition();    final Condition notEmpty = lock.newCondition();    final Object[] items = new Object[100];   int putptr, takeptr, count;   public void put(Object x) throws InterruptedException {     lock.lock();     try {       while (count == items.length)          notFull.await();       items[putptr] = x;        if (++putptr == items.length) putptr = 0;       ++count;       notEmpty.signal();     } finally {       lock.unlock();     }   }   public Object take() throws InterruptedException {     lock.lock();     try {       while (count == 0)          notEmpty.await();       Object x = items[takeptr];        if (++takeptr == items.length) takeptr = 0;       --count;       notFull.signal();       return x;     } finally {       lock.unlock();     }   }  } 











0 0