精选文章 多线程设计模式

多线程设计模式

作者:iteye_1465 时间: 2021-07-06 09:11:25
iteye_1465 2021-07-06 09:11:25
【摘要】
                      
多线程设计模式有很多模式,我用简约的几行伪代码表示吧,如下: 
  
模式1:简单的synchronized+wait/notify 
最简单的wait/notify的应用,get的时候,如果没有数据就锁住对象,使当前线程等待,当有数据put的时候,调用notify来唤醒等待的线程,释放对象。如下: 
private queue;

publi...

 

多线程设计模式有很多模式,我用简约的几行伪代码表示吧,如下:

 

模式1:简单的synchronized+wait/notify

最简单的wait/notify的应用,get的时候,如果没有数据就锁住对象,使当前线程等待,当有数据put的时候,调用notify来唤醒等待的线程,释放对象。如下:

private queue;

public synchronized Object get(){ while(queue.size<=0){wait()}>

 

模式2:synchronized+return

模式2不同于模式1,是get的时候直接返回,线程不等待。如下:

private queue;

public synchronized Object get(){ return queue.size<=0?>

 

 

 

模式3:synchronized+wait/notify+buffer

模式3是对模式1的优化,增加了一个“缓存”,当put的时候超过大小需要wait,防止无限制的put操作而导致溢出。

private queue;
private count=0;
private bufferSize=10;
public synchronized Object get(){ while(count<=0)wait();>=bufferSize) wait(); count++; queue.put(obj); notifyAll();
}

 

 

模式4:读写锁

 

 

模式5:new工作线程

  模式5是在前几个模式的基础上新增加了工作任务线程,当有新请求过来的时候就新建工作线程,如下handle方法:

private queue;
private count=0;
private bufferSize=10;
private synchronized Object get(){ while(count<=0)wait();>=bufferSize) wait(); count++; queue.put(obj); notifyAll();
}

public void handle(){
  new Thread(this.get()){ public void run(){ System.out.println("Do work..");}}.start();
}

 

模式6:用线程池来优化工作线程

 模式5的坏处是每次一个新的工作,需要new一个新的线程来做,这样开销太大,于是引入的“线程池”,如下:

private queue;
private count=0;
private bufferSize=10;
private final max_wk=20;
private final WorkerThread[] pool=new  WorkerThread[max_wk];


private synchronized Object get(){ while(count<=0)wait();>=bufferSize) wait(); count++; queue.put(obj); notifyAll();
}

public void startWrok(){ for(int i=0;i

 

模式7:终止线程

 工作线程在做工作的时候先判断是否需要终止线程。

 

public void stopWork(){ stopWork=true; interrupt();
}

public void run(){
  try{ while(!stopWork){ do something... } }catch( InterruptedException e){ }
}

模式8:ThreadLocal模式 

 目前很多frame比较经典的保持线程安全的模式,他像一个保险箱一样保管着所有线程对象,他需要做点额外的工作,比如把线程对象set()和get()。

 

 

class RealWork
{ public void doSomething(){// 工作 ... }
}

class Work
{ private static final ThreadLocal local=new ThreadLocal();
  public void doSomething(){ getReal().doSomething(); } private void getReal(){ // 获取所处当前线程的资源 RealWork obj=local.get(); if(obj==null){ obj=new RealWork(Thread.currentThread().getName()); local.set(obj); } return obj;
  }
} 

 

 

 

附录:

transient Thread owner; public boolean put(E o) { if (o == null) throw new NullPointerException(); final AtomicInteger count = this.count;// 大小计数器 if (count.get() == capacity) return false; int c = -1; if (compareAndSetState(0, 1))// 检测当前状态,如果没有线程写,那么保存当前线程 owner = Thread.currentThread(); else acquire(1);// 否则,等待正在写入的线程 try { if (count.get() < capacity) { insert(o); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); // } } finally { if (tryRelease(1)) { Node h = head; // 等待线程链表 if (h != null && h.waitStatus != 0) unparkSuccessor(h); } } if (c == 0) signalNotEmpty(); return c >= 0; // 精炼的写法 }

 

 

5.0 以前,锁定的功能是由 Synchronized 关键字来实现的,这样做存在几个问题:

 

  • 每次只能对一个对象进行锁定。若需要锁定多个对象,编程就比较麻烦,一不小心就会出现死锁现象。
  • 如果线程因拿不到锁定而进入等待状况,是没有办法将其打断的

 

ReentrantLock锁等待线程队列:

 

获得当前等待取锁线程:

 public final Collection getQueuedThreads() { ArrayList list = new ArrayList(); for (Node p = tail; p != null; p = p.prev) { Thread t = p.thread; if (t != null) list.add(t); } return list; }

 

 

附录:

关于Daemon线程:

我是在偶然之间用到的Daemon线程,当时却没有发现什么特别之处,直到今天才意识到微妙且严重的差别,如下:

Any Java thread can be a daemon thread. Daemon threads are service providers for other threads running in the same process as the daemon thread. The run() method for a daemon thread is typically an infinite loop that waits for a service request.
When the only remaining threads in a process are daemon threads, the interpreter exits. This makes sense because when only daemon threads remain, there is no other thread for which a daemon thread can provide a service.
做过实验才明白,原来当只存在Daemon线程且没有用户线程的时候,JVM退出,以前写thread的时候还真没注意,实验如下:

 

public class DaemonThread extends Thread{ public void  run(){ while(true){ System.out.println("I'm daemon"); } } public static void main(String args[]){ DaemonThread daemon=new DaemonThread(); daemon.setDaemon(true); daemon.start(); } }  

 

 

可以看到JVM很快就退出了,虽然这里是一个while(true)循环。

 

勿删,copyright占位
您找到想要的结果了吗?
多线程设计模式
提交成功!非常感谢您的反馈,我们会继续努力做到更好
分享文章到微博
分享文章到朋友圈

上一篇:以架构师为目标?读程序员职业规划有感

下一篇:SSH 连接超时解决办法

CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。
多线程设计模式介绍:华为云为您免费提供多线程设计模式在博客、论坛、帮助中心等栏目的相关文章,同时还可以通过 站内搜索 查询更多多线程设计模式的相关内容。| 移动地址: 多线程设计模式 | 写博客