JAvaマルチスレッドまとめ学習-Queue、コンテナ、単例モード

8762 ワード

1、単例モードはマルチスレッドをサポートする
単例モード:よく使われる2つのモード:餓漢モード怠け者モードですが、この2つのモードはマルチスレッドアプリケーションシーンでは安全ではありません.
マルチスレッドに適用し、スレッドの安全を保障するために、double check instance、static inner classの2つを使用します.
(1)static inner class
package thread;

/**
 *     ,      
 * static inner class
 *        
 */
public class SingleInner {

	private static class Singleton{
		private static Singleton single = new Singleton();
	}
	
	public static Singleton getInstance(){
		return Singleton.single;
	}
}

(2)double check instance
public class Singleton{
	//      ,     
	private static Singleton instance = null;

	//      ,      
	private Singleton(){
	}

	private static synchronized void syncInit(){
		if(instance == null){
			instance = new Singleton();
		}
	}
	
	public static Singleton getInstance(){
		if(instance == null){
			syncInit();
		}
		return instance;	
	}
}

2、同期クラスコンテナ、同時クラスコンテナ同期クラス:vector hashTable(下部にsynchronid修飾を付け、同期を実現したが、同時効率に影響する)
同時クラス:Queue、concurrentMap、LinkedBlockingQueue、CopyOnWrite
(1)ConcurrentHashMap:セグメントsegmentで複数のセグメントを分割し、各セグメントはhashTableに相当し、対応するロックがあり、最大16個のセグメントをサポートする
スレッドごとに異なるセグメントにアクセス
作用:ロック粒度を減らし、ロック競合を減らす
最下位でvolatileキーワードを大量に使用し、共有変数を実現
(2)Copy-ON-Write(COW)CopyOnWriteArrayListとCopyOnWriteArraySet
書き込み時にコピーしたコンテナ、読み書き分離を実現
スレッドがコンテナを操作(削除)すると、コンテナを直接操作するのではなく、同じコンテナをコピーして操作し、操作が完了すると、元のコンテナのポインタをコピーしたコンテナに指します.
他のスレッドが読み取りを行う場合、元のコンテナを直接読み取り、読み書き相分離を実現する
適用シーン:読み書きが少ない場合
3、同時queue ConcurentLinkedQueue:非ブロック、性能が高く、高同時
BlockingQueue:ブロックされた
ConcurentLinkedQueue:
先頭が先頭で、先頭が先頭で、末尾が最も近いのでnull値は許されません
add()offer()は要素を入れて、ConcurentLinkedQueueの中で区別がありません
Poll()peek()ヘッダ要素、前者は要素を削除し、後者は削除しない
BlockingQueue:,ブロック
1、ArrayBlockingQueue、配列、境界行列に基づいて、ブロックする
2、LinkedBlockingQueue無境界キュー、ブロック
3、synchronousQueue:バッファのないキューでは要素を追加できません
4、priorityBlockingQueue:優先順位に基づくブロックキューで、キューに入ったオブジェクトはcomparableインタフェースが先進的な先出しに従わないことを実現しなければならない
5、DelayQueue:要素はdelayedインタフェースを実現しなければならない.要素は遅延時間に達しなければ、取り出されない
(1)ConcurentLinkedQueue
package queue;

import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ConcurrentLinkedQueue    ,   ,   
 *     ,     ,     ,    null 
 * add() offer()    , ConcurentLinkedQueue    
 * poll() peek()     ,      ,    
 */
public class UseConcurrentQueue {

	public static void main(String[] args) {
		ConcurrentLinkedQueue q = new ConcurrentLinkedQueue();
		
		q.add("a");
		q.add("b");
		q.add("c");
		q.add("d");
		q.offer("e");
		q.offer("f");
		
		System.out.println(q.size());
		System.out.println(q.poll());
		System.out.println(q.size());
		System.out.println(q.peek());
		System.out.println(q.size());
	}
}

(2)BlockingQueue(ArrayBlockingQueue、linkedBlockingQueue、SynchronousQueue)
package queue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * BlockingQueue:   
 * ArrayBlockingQueue:     ,   
 * linkedBlockingQueue:   ,     ,    ,     ,     ,     
 * SynchronousQueue:       ,take()       ,   take ,    add,  add   ,     
 *
 */
public class UseBlockingQueue {
	public static void main(String[] args) throws Exception{
		//ArrayBlockingQueue
		ArrayBlockingQueue aq = new ArrayBlockingQueue(5);
		aq.add("a");
		aq.add("b");
		aq.put("c");
		aq.put("d");
		aq.offer("e");
		aq.offer("f");
		System.out.println("ArrayBlockingQueue:"+aq);
		
		
		//linkedBlockingQueue
		LinkedBlockingQueue lq = new LinkedBlockingQueue<>();
		lq.add("a");
		lq.add("b");
		lq.put("c");
		lq.put("d");
		lq.offer("e");
		lq.offer("f");
		System.out.println("LinkedBlockingQueue  :"+lq);
		
		LinkedBlockingQueue lq2 = new LinkedBlockingQueue<>(4);
		lq2.add("a");
		lq2.add("b");
		lq2.put("c");
		lq2.put("d");
		lq2.offer("e");
		lq2.offer("f");
		System.out.println("LinkedBlockingQueue  :"+lq2);
		
		//synchronousQueue
		final SynchronousQueue sq = new SynchronousQueue<>();
		//sq.add("a");		//   java.lang.IllegalStateException: Queue full
		Thread t1 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					sq.take();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			}
			
		});
		t1.start();
		
		Thread t2 = new Thread(new Runnable(){

			@Override
			public void run() {
				sq.add("a");
				System.out.println("SynchronousQueue:"+sq);
			}
			
		});
		t2.start();
	}
}

(3)PriorityBlockingQueue.シミュレーションシーン:タスクがある場合、タスクIDに従って優先度に従って解放されます.
package queue;

import java.util.concurrent.PriorityBlockingQueue;

import queue.priority.Task;

/**
 * PriorityBlockingQueue:     
 *           comparable  ,     
 *       take   ,          (       )
 * 
 */
public class UsePriorityBlockingQueue {
	
	public static void main(String[] args) throws Exception{
		
		PriorityBlockingQueue pq = new PriorityBlockingQueue();
		
		Task t1 = new Task();
		t1.setId(1);
		t1.setName("  1");
		
		Task t2 = new Task();
		t2.setId(4);
		t2.setName("  2");
		
		Task t3 = new Task();
		t3.setId(3);
		t3.setName("  3");
		
		pq.add(t1);
		pq.add(t2);
		pq.add(t3);
		
		System.out.println("  :"+pq.toString());
		System.out.println(pq.take().getId());
		System.out.println("  :"+pq.toString());
		System.out.println(pq.take().getId());
		System.out.println(pq.take().getId());
	}
}
package queue.priority;

public class Task implements Comparable{
	private int id;
	private String name;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public int compareTo(Task o) {
		return this.id > o.id ? 1 : (this.id > o.id ? -1 : 0);
	}
	
	
	public String toString(){
		return this.id + "," + this.name;
	}
}

実行結果:
コンテナ:[1,タスク1,4,タスク2,3,タスク3]1コンテナ:[3,タスク3,4,タスク2]3 4
(4)DelayQueue,シミュレーションシーン,ネットカフェでチェックイン,時間までダウン
package queue;

import java.util.concurrent.DelayQueue;

import queue.delay.Wangmin;

/**
 * DelayQueue:    
 *       delayed  
 *            ,     
 */
public class UseDelayQueue implements Runnable{

	DelayQueue dq = new DelayQueue();
	
	public void shangji(int id, String name, int money){
		Wangmin wm = new Wangmin(id,name,1000*money+System.currentTimeMillis());
		dq.add(wm);
		System.out.println("  :"+name+"    ,    "+money+" ");
	}
	
	public void xiaji(Wangmin wm){
		System.out.println("  :"+wm.getName()+"  。。。");
	}
	
	@Override
	public void run() {
		while(true){
			try {
				Wangmin wm = dq.take();
				xiaji(wm);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		
		UseDelayQueue udq = new UseDelayQueue();
		Thread t = new Thread(udq);
		t.start();
		
		udq.shangji(1,"  ",1);
		udq.shangji(2,"  ",10);
		udq.shangji(3,"  ",5);
		
	}

}
package queue.delay;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 *   
 *    Delayed  
 *     getDelay、compareTo  
 */
public class Wangmin implements Delayed{
	private int id;
	private String name;
	private long endtime;
	private TimeUnit timeUnit = TimeUnit.SECONDS;//    , 
	
	//    
	public Wangmin(int id, String name, long endtime){
		this.id=id;
		this.name = name;
		this.endtime = endtime;
	}

	@Override
	public int compareTo(Delayed delay) {
		Wangmin w = (Wangmin)delay;
		return this.getDelay(this.timeUnit) > w.getDelay(this.timeUnit) ? 1 : 0;
	}

	@Override
	public long getDelay(TimeUnit arg0) {
		return endtime - System.currentTimeMillis();
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public long getEndtime() {
		return endtime;
	}

	public void setEndtime(long endtime) {
		this.endtime = endtime;
	}
}

実行結果:
ネットユーザー:張三が搭乗を開始し、搭乗時間は1秒
ネットユーザー:李四は飛行機に乗ることを始めて、飛行機に乗る時間の10秒
ネットユーザー:王五は飛行機に乗ることを始めて、飛行機に乗る時間の5秒
网民:张三下机..
ネットユーザー:王五下机..
ネットユーザー:李四下机..