多线程之并发编程、线程安全数据结构——JAVA

目录

 

一、Thread/Runnable/Thread组管理

二、Executor:

三、Fork-Join框架


一、Thread/Runnable/Thread组管理

  • 线程的集合,
  • 树形结构,大线程组可以包括小线程组,
  • 可以通过enumerate方法遍历组内进程执行操作,
  • 能有效的管理多个进程,但是还是存在管理效率低,
  • 任务分配和执行过程高度耦合,
  • 重复创建线程,关闭线程操作,无法重用线程。

1.创建线程组:ThreadGroup threadGroup = new ThreadGroup("Searcher");

2.将线程绑定到线程组中方法(此处需注意线程用Runnable方法实现):Thread thread=new Thread(threadGroup, searchTask);

3.遍历线程组方法:

Thread[] threads=new Thread[threadGroup.activeCount()];//初始化线程数组
		threadGroup.enumerate(threads);//将线程组中的各个线程放入线程数组中去
		for (int i=0; i<threadGroup.activeCount(); i++) {
			System.out.printf("Thread %s: %s\n",threads[i].getName(),threads[i].getState());//输出线程的名字和状态
		}

示例1:

package threadgroup;

import java.util.concurrent.TimeUnit;

public class Main {

	public static void main(String[] args) {

		// 创建线程组
		ThreadGroup threadGroup = new ThreadGroup("Searcher");
		Result result=new Result();

		// 创建一个任务,以serchTask为模板10个线程完成
		Searcher searchTask=new Searcher(result);
		for (int i=0; i<10; i++) {
			Thread thread=new Thread(threadGroup, searchTask);
			thread.start();
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("========华丽丽0=======");
		
		// 查看线程组消息
		System.out.printf("active 线程数量: %d\n",threadGroup.activeCount());
		System.out.printf("线程组信息明细\n");
		threadGroup.list();
		System.out.println("========华丽丽1=======");

		// 遍历线程组
		Thread[] threads=new Thread[threadGroup.activeCount()];
		threadGroup.enumerate(threads);
		for (int i=0; i<threadGroup.activeCount(); i++) {
			System.out.printf("Thread %s: %s\n",threads[i].getName(),threads[i].getState());
		}
		System.out.println("========华丽丽2=======");

		// Wait for the finalization of the Threadds
		waitFinish(threadGroup);
		
		// Interrupt all the Thread objects assigned to the ThreadGroup
		threadGroup.interrupt();
	}

	public static void waitFinish(ThreadGroup threadGroup) {
		while (threadGroup.activeCount()>9) {//当十个进程都在运行
			try {
				TimeUnit.SECONDS.sleep(1);//主线程休息一秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
package threadgroup;

/**
 * 搜索结果类
 *
 */
public class Result {
	
	private String name;	
	public String getName() {
		return name;
	}	
	public void setName(String name) {
		this.name = name;
	}

}
package threadgroup;

import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class Searcher implements Runnable {

	private Result result;
	
	public Searcher(Result result) {
		this.result=result;
	}

	@Override
	public void run() {
		String name=Thread.currentThread().getName();
		System.out.printf("Thread %s: 启动\n",name);
		try {
			doTask();
			result.setName(name);
		} catch (InterruptedException e) {
			System.out.printf("Thread %s: 被中断\n",name);
			return;
		}
		System.out.printf("Thread %s: 完成\n",name);
	}
	
	private void doTask() throws InterruptedException {
		Random random=new Random((new Date()).getTime());
		int value=(int)(random.nextDouble()*100);
		System.out.printf("Thread %s: %d\n",Thread.currentThread().getName(),value);
		TimeUnit.SECONDS.sleep(value);
	}
}

二、Executor:

  • 线程可以重复利用(不用每次都new),分离任务和执行者的创建。
  • 程序员无需关心线程池执行任务的过程,预先设好多个Thread,可弹性增加。
  • callable接口实现线程可以返回值

实现方法,首先线程类中需要实现Callable接口,同时实现call方法返回相关值。

1.创建线程池ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);(线程池容量为4,若不指定则线程池的容量会随线程的增多而增大)

2.建立链表List<Future<Integer>> resultList=new ArrayList<>();来保存结果返回

3.提交线程到线程池中运行Future<Integer> result=executor.submit(calculator);

4.根据链表存储获取每一个线程的结果,再isDone判断是否线程计算结束

5.再根据get函数线程结果中提取计算结果

具体代码示例2:

package executor.example2;

import java.util.Random;
import java.util.concurrent.Callable;

public class SumTask implements Callable<Integer> {
	//定义每个线程计算的区间
	private int startNumber;
	private int endNumber;
	
	public SumTask(int startNumber, int endNumber){
		this.startNumber=startNumber;
		this.endNumber=endNumber;
	}
	
	@Override
	public Integer call() throws Exception {
		int sum = 0;
		for(int i=startNumber; i<=endNumber; i++)
		{
			sum = sum + i;
		}
		
		Thread.sleep(new Random().nextInt(1000));
		
		System.out.printf("%s: %d\n",Thread.currentThread().getName(),sum);
		return sum;
	}
}
package executor.example2;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;


public class SumTest {

	public static void main(String[] args) {
		
		// 执行线程池
		ThreadPoolExecutor executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(4);
		
		List<Future<Integer>> resultList=new ArrayList<>();

		//统计1-1000总和,分成10个任务计算,提交任务
		for (int i=0; i<10; i++){
			SumTask calculator=new SumTask(i*100+1, (i+1)*100);
			Future<Integer> result=executor.submit(calculator);
			resultList.add(result);
		}
		
		// 每隔50毫秒,轮询等待10个任务结束
		do {
			System.out.printf("Main: 已经完成多少个任务: %d\n",executor.getCompletedTaskCount());
			for (int i=0; i<resultList.size(); i++) {
				Future<Integer> result=resultList.get(i);
				System.out.printf("Main: Task %d: %s\n",i,result.isDone());//当isDone为true则线程结束
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (executor.getCompletedTaskCount()<resultList.size());
		
		// 所有任务都已经结束了,综合计算结果		
		int total = 0;
		for (int i=0; i<resultList.size(); i++) {
			Future<Integer> result=resultList.get(i);
			Integer sum=null;
			try {
				sum=result.get();//获取call方法的值
				total = total + sum;
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		System.out.printf("1-1000的总和:" + total);
		
		// 关闭线程池
		executor.shutdown();
	}
}

也可以单独设置线程池类从而更加易于理解:

package executor.example1;

public class Main {

	public static void main(String[] args) throws InterruptedException {
		// 创建一个执行服务器
		Server server=new Server();
		
		// 创建100个任务,并发给执行器,等待完成
		for (int i=0; i<100; i++){
			Task task=new Task("Task "+i);
			Thread.sleep(10);
			server.submitTask(task);
		}		
		server.endServer();
	}
}
package executor.example1;

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 执行服务器
 *
 */
public class Server {
	
	//线程池
	private ThreadPoolExecutor executor;
	
	public Server(){
		executor=(ThreadPoolExecutor)Executors.newCachedThreadPool();
		//executor=(ThreadPoolExecutor)Executors.newFixedThreadPool(5);
	}
	
	//向线程池提交任务
	public void submitTask(Task task){
		System.out.printf("Server: A new task has arrived\n");
		executor.execute(task); //执行  无返回值
		
		System.out.printf("Server: Pool Size: %d\n",executor.getPoolSize());
		System.out.printf("Server: Active Count: %d\n",executor.getActiveCount());
		System.out.printf("Server: Completed Tasks: %d\n",executor.getCompletedTaskCount());
	}

	public void endServer() {
		executor.shutdown();
	}
}
package executor.example1;

import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
 * Task 任务类
 * @author Tom
 *
 */
public class Task implements Runnable {

	private String name;
	
	public Task(String name){
		this.name=name;
	}
	
	public void run() {
		try {
			Long duration=(long)(Math.random()*1000);
			System.out.printf("%s: Task %s: Doing a task during %d seconds\n",Thread.currentThread().getName(),name,duration);
			Thread.sleep(duration);			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.printf("%s: Task %s: Finished on: %s\n",Thread.currentThread().getName(),name,new Date());
	}

}

三、Fork-Join框架

能够分解、分治、合并(可以分治编程),适合整体任务量不好确定的场合,这个函数内类似就写好了递归的方法函数,不用自己写递归,个人认为这个最简单方便。
 

import java.math.BigInteger;
import java.util.concurrent.RecursiveTask;

//分任务求和
public class SumTask extends RecursiveTask<Long> {
	
	private int start;
	private int end;

	public SumTask(int start, int end) {
		this.start = start;
		this.end = end;
	}

	public static final int threadhold = 5;

	@Override
	protected Long compute() {
		Long sum = 0L;
		
		// 如果任务足够小, 就直接执行
		boolean canCompute = (end - start) <= threadhold;
		if (canCompute) {
			for (int i = start; i <= end; i++) {
				sum = sum + i;				
			}
		} else {
			// 任务大于阈值, 分裂为2个任务
			int middle = (start + end) / 2;
			SumTask subTask1 = new SumTask(start, middle);
			SumTask subTask2 = new SumTask(middle + 1, end);

			invokeAll(subTask1, subTask2);//合并两个线程,相当于不用自己写递归了,非常的方便。

			Long sum1 = subTask1.join();
			Long sum2 = subTask2.join();

			// 结果合并
			sum = sum1 + sum2;
		}
		return sum;
	}
}

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;

//分任务求和
public class SumTest {
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建执行线程池
    	ForkJoinPool pool = new ForkJoinPool();
    	//ForkJoinPool pool = new ForkJoinPool(4);
    	
    	//创建任务
        SumTask task = new SumTask(1, 10000000);
        
        //提交任务
        ForkJoinTask<Long> result = pool.submit(task);
        
        //等待结果
        do {
			System.out.printf("Main: Thread Count: %d\n",pool.getActiveThreadCount());//线程池里卖弄有多少个线程
			System.out.printf("Main: Paralelism: %d\n",pool.getParallelism());//线程中的并行度有多少
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (!task.isDone());//判断整体任务是否结束
        
        //输出结果
        System.out.println(result.get().toString());
    }
}

 四、线程安全数据结构:

package list;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

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

        //线程不安全
        List<String> unsafeList = new ArrayList<String>();
        //线程安全
        List<String> safeList1 = Collections.synchronizedList(new ArrayList<String>());
        //线程安全
        CopyOnWriteArrayList<String> safeList2 = new CopyOnWriteArrayList<String>();

        ListThread t1 = new ListThread(unsafeList);
        ListThread t2 = new ListThread(safeList1);
        ListThread t3 = new ListThread(safeList2);

        for(int i = 0; i < 10; i++){
            Thread t = new Thread(t1, String.valueOf(i));
            t.start();
        }
        for(int i = 0; i < 10; i++) {
            Thread t = new Thread(t2, String.valueOf(i));
            t.start();
        }
        for(int i = 0; i < 10; i++) {
            Thread t = new Thread(t3, String.valueOf(i));
            t.start();
        }

        //等待子线程执行完
        Thread.sleep(2000);
 
        System.out.println("listThread1.list.size() = " + t1.list.size());
        System.out.println("listThread2.list.size() = " + t2.list.size());
        System.out.println("listThread3.list.size() = " + t3.list.size());

        //输出list中的值
        System.out.println("unsafeList:");
        for(String s : t1.list){
            if(s == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(s + "  ");
            }
        }
        System.out.println();
        System.out.println("safeList1:");
        for(String s : t2.list){
        	if(s == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(s + "  ");
            }
        }
        System.out.println();
        System.out.println("safeList2:");
        for(String s : t3.list){
        	if(s == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(s + "  ");
            }
        }
    }
}

class ListThread implements Runnable{
	public List<String> list;

    public ListThread(List<String> list){
        this.list = list;
    }

    @Override
    public void run() {
    	int i = 0;
    	while(i<10)
    	{
    		try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            //把当前线程名称加入list中
            list.add(Thread.currentThread().getName());
            i++;
    	}        
    }
}

输出:
listThread1.list.size() = 95
listThread2.list.size() = 100
listThread3.list.size() = 100
unsafeList:
6  5  4  3  2  1  9  8  7  0  6  5  4  3  2  1  9  8  7  0  1  2  3  4  5  6  0  7  8  9  6  5  4  null  2  1  0  7  8  9  1  2  4  6  5  9  8  7  0  null  5  4  1  2  3  0  7  8  9  2  1  4  5  6  9  7  0  6  5  3  4  2  1  0  8  7  9  5  4  2  1  8  0  7  9  1  2  4  5  6  3  9  7  8  0  
safeList1:
1  9  8  7  6  5  4  3  2  0  1  9  8  7  6  5  4  3  2  0  1  0  2  3  4  5  6  7  8  9  1  0  3  2  4  6  5  7  8  9  1  9  8  7  5  6  4  2  3  0  1  0  3  2  4  6  5  7  8  9  1  8  7  5  9  6  4  2  3  0  1  0  3  2  4  7  6  9  5  8  1  0  3  2  4  7  6  9  5  8  1  5  8  9  7  6  4  2  3  0  
safeList2:
3  2  1  0  5  6  9  8  7  4  3  2  1  0  6  5  5  6  4  7  8  9  0  2  3  1  5  6  8  4  9  0  3  1  7  2  6  5  1  3  0  9  4  2  8  7  6  5  7  4  2  8  9  0  3  1  6  5  8  2  9  7  4  0  1  3  6  5  4  9  8  2  7  1  0  3  5  6  2  7  4  9  1  3  0  8  6  5  4  7  2  9  1  0  3  8  9  7  4  8  

package set;

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

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

        //线程不安全
        Set<String> unsafeSet = new HashSet<String>();
        //线程安全
        Set<String> safeSet1 = Collections.synchronizedSet(new HashSet<String>());
        //线程安全
        CopyOnWriteArraySet<String> safeSet2 = new CopyOnWriteArraySet<String>();

        SetThread t1 = new SetThread(unsafeSet);
        SetThread t2 = new SetThread(safeSet1);
        SetThread t3 = new SetThread(safeSet2);

        //unsafeSet的运行测试
        for(int i = 0; i < 10; i++){
        	Thread t = new Thread(t1, String.valueOf(i));
        	t.start();
        }
        for(int i = 0; i < 10; i++) {
        	Thread t = new Thread(t2, String.valueOf(i));
            t.start();
        }
        for(int i = 0; i < 10; i++) {
        	Thread t = new Thread(t3, String.valueOf(i));
            t.start();
        }

        //等待子线程执行完
        Thread.sleep(2000);
 
        System.out.println("setThread1.set.size() = " + t1.set.size());
        System.out.println("setThread2.set.size() = " + t2.set.size());
        System.out.println("setThread3.set.size() = " + t3.set.size());

        //输出set中的值
        System.out.println("unsafeSet:");
        for(String element:t1.set){
            if(element == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(element + "  ");
            }
        }
        System.out.println();
        System.out.println("safeSet1:");
        for(String element:t2.set){
        	if(element == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(element + "  ");
            }
        }
        System.out.println();
        System.out.println("safeSet2:");
        for(String element:t3.set){
        	if(element == null){
            	System.out.print("null  ");
            }
            else
            {
            	System.out.print(element + "  ");
            }
        }
    }
}

class SetThread implements Runnable{
	public Set<String> set;

    public SetThread(Set<String> set){
        this.set = set;
    }

    @Override
    public void run() {
    	int i = 0;
    	while(i<10)
    	{
    		i++;
    		try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            //把当前线程名称加入list中
            set.add(Thread.currentThread().getName() + i);
    	}        
    }
}
输出:
setThread1.set.size() = 96
setThread2.set.size() = 100
setThread3.set.size() = 100
unsafeSet:
44  88  01  45  89  02  46  03  47  04  48  05  49  06  07  08  09  110  310  510  710  91  910  92  93  94  51  95  52  96  53  97  54  98  11  55  99  12  56  13  57  14  58  15  59  16  17  18  19  61  62  63  64  21  65  22  66  23  67  24  68  25  69  26  27  28  29  010  210  410  610  810  72  73  74  31  75  32  76  33  77  34  78  35  79  36  37  38  39  82  83  84  41  85  42  86  43  87  
safeSet1:
88  01  89  02  03  04  05  06  07  08  09  110  510  91  910  92  93  94  95  96  97  98  11  99  12  13  14  15  16  17  18  19  21  22  23  24  25  26  27  28  29  010  410  810  31  32  33  34  35  36  37  38  39  41  42  43  44  45  46  47  48  49  310  710  51  52  53  54  55  56  57  58  59  61  62  63  64  65  66  67  68  69  210  610  71  72  73  74  75  76  77  78  79  81  82  83  84  85  86  87  
safeSet2:
51  71  61  21  31  11  01  91  81  41  72  62  02  12  32  22  52  82  42  92  73  23  33  03  13  53  63  43  93  83  64  54  14  34  24  74  04  84  94  44  55  15  35  25  65  75  95  45  85  05  76  66  26  36  16  56  06  86  46  96  57  17  37  27  67  77  07  87  47  97  18  38  58  68  78  28  98  48  88  08  59  39  19  29  79  69  09  89  49  99  510  310  110  710  610  210  410  910  810  010  

package map;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

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

        //线程不安全
        Map<Integer,String> unsafeMap = new HashMap<Integer,String>();
        //线程安全
        Map<Integer,String> safeMap1 = Collections.synchronizedMap(new HashMap<Integer,String>());
        //线程安全
        ConcurrentHashMap<Integer,String> safeMap2 = new ConcurrentHashMap<Integer,String>();

        MapThread t1 = new MapThread(unsafeMap);
        MapThread t2 = new MapThread(safeMap1);
        MapThread t3 = new MapThread(safeMap2);

        //unsafeMap的运行测试
        for(int i = 0; i < 10; i++){
        	Thread t = new Thread(t1);
        	t.start();
        }       
        for(int i = 0; i < 10; i++) {
        	Thread t = new Thread(t2);
            t.start();
        }
        for(int i = 0; i < 10; i++) {
        	Thread t = new Thread(t3);
            t.start();
        }

        //等待子线程执行完
        Thread.sleep(2000);
 
        System.out.println("mapThread1.map.size() = " + t1.map.size());
        System.out.println("mapThread2.map.size() = " + t2.map.size());
        System.out.println("mapThread3.map.size() = " + t3.map.size());

        //输出set中的值
        System.out.println("unsafeMap:");
        Iterator iter = t1.map.entrySet().iterator();
        while(iter.hasNext()) {
            Map.Entry<Integer,String> entry = (Map.Entry<Integer,String>)iter.next();
            // 获取key
            System.out.print(entry.getKey() + ":");
            // 获取value
            System.out.print(entry.getValue() + " ");
        }
        System.out.println();
        
        System.out.println("safeMap1:");
        iter = t2.map.entrySet().iterator();
        while(iter.hasNext()) {
            Map.Entry<Integer,String> entry = (Map.Entry<Integer,String>)iter.next();
            // 获取key
            System.out.print(entry.getKey() + ":");
            // 获取value
            System.out.print(entry.getValue() + " ");
        }

        System.out.println();
        System.out.println("safeMap2:");
        iter = t3.map.entrySet().iterator();
        while(iter.hasNext()) {
            Map.Entry<Integer,String> entry = (Map.Entry<Integer,String>)iter.next();
            // 获取key
            System.out.print(entry.getKey() + ":");
            // 获取value
            System.out.print(entry.getValue() + " ");
        }
        System.out.println();
        System.out.println("mapThread1.map.size() = " + t1.map.size());
        System.out.println("mapThread2.map.size() = " + t2.map.size());
        System.out.println("mapThread3.map.size() = " + t3.map.size());
    }
}

class MapThread implements Runnable
{
	public Map<Integer,String> map;

    public MapThread(Map<Integer,String> map){
        this.map = map;
    }

    @Override
    public void run() {
        int i=0;
        
        while(i<100)
        {
        	//把当前线程名称加入map中
            map.put(i++,Thread.currentThread().getName());
            try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }        
    }
}
输出:
mapThread1.map.size() = 122
mapThread2.map.size() = 100
mapThread3.map.size() = 100
unsafeMap:
0:Thread-9 1:Thread-9 2:Thread-3 3:Thread-7 4:Thread-3 5:Thread-7 6:Thread-7 7:Thread-3 8:Thread-7 9:Thread-3 10:Thread-7 11:Thread-6 12:Thread-7 13:Thread-7 14:Thread-3 15:Thread-7 16:Thread-6 17:Thread-5 18:Thread-5 19:Thread-6 20:Thread-5 21:Thread-6 22:Thread-5 23:Thread-5 24:Thread-9 25:Thread-5 26:Thread-9 27:Thread-5 28:Thread-5 29:Thread-6 30:Thread-5 31:Thread-9 32:Thread-5 33:Thread-5 34:Thread-3 35:Thread-5 36:Thread-3 37:Thread-5 38:Thread-5 39:Thread-3 40:Thread-5 41:Thread-3 42:Thread-7 43:Thread-7 44:Thread-6 45:Thread-9 46:Thread-6 47:Thread-9 48:Thread-6 49:Thread-9 50:Thread-6 51:Thread-9 52:Thread-6 53:Thread-5 54:Thread-6 55:Thread-5 56:Thread-6 57:Thread-5 58:Thread-6 59:Thread-5 60:Thread-5 61:Thread-6 62:Thread-5 63:Thread-6 64:Thread-5 65:Thread-5 66:Thread-6 67:Thread-5 68:Thread-6 69:Thread-5 70:Thread-7 71:Thread-3 72:Thread-7 73:Thread-7 74:Thread-9 75:Thread-9 76:Thread-3 77:Thread-9 78:Thread-3 79:Thread-9 80:Thread-9 81:Thread-3 82:Thread-9 83:Thread-3 84:Thread-9 85:Thread-9 86:Thread-3 87:Thread-7 88:Thread-3 89:Thread-7 90:Thread-9 91:Thread-6 92:Thread-9 93:Thread-6 94:Thread-9 95:Thread-9 96:Thread-6 97:Thread-9 98:Thread-6 99:Thread-7 
safeMap1:
0:Thread-19 1:Thread-18 2:Thread-19 3:Thread-13 4:Thread-19 5:Thread-13 6:Thread-13 7:Thread-19 8:Thread-13 9:Thread-19 10:Thread-13 11:Thread-19 12:Thread-18 13:Thread-13 14:Thread-19 15:Thread-11 16:Thread-14 17:Thread-13 18:Thread-13 19:Thread-19 20:Thread-13 21:Thread-19 22:Thread-13 23:Thread-13 24:Thread-19 25:Thread-13 26:Thread-19 27:Thread-11 28:Thread-13 29:Thread-14 30:Thread-11 31:Thread-13 32:Thread-11 33:Thread-11 34:Thread-10 35:Thread-11 36:Thread-10 37:Thread-11 38:Thread-19 39:Thread-13 40:Thread-19 41:Thread-13 42:Thread-14 43:Thread-14 44:Thread-13 45:Thread-14 46:Thread-13 47:Thread-11 48:Thread-13 49:Thread-11 50:Thread-13 51:Thread-11 52:Thread-13 53:Thread-19 54:Thread-13 55:Thread-19 56:Thread-13 57:Thread-19 58:Thread-13 59:Thread-19 60:Thread-19 61:Thread-11 62:Thread-14 63:Thread-11 64:Thread-14 65:Thread-14 66:Thread-13 67:Thread-11 68:Thread-11 69:Thread-10 70:Thread-10 71:Thread-13 72:Thread-10 73:Thread-14 74:Thread-13 75:Thread-13 76:Thread-11 77:Thread-13 78:Thread-11 79:Thread-13 80:Thread-13 81:Thread-11 82:Thread-13 83:Thread-11 84:Thread-13 85:Thread-13 86:Thread-11 87:Thread-13 88:Thread-11 89:Thread-13 90:Thread-19 91:Thread-11 92:Thread-19 93:Thread-11 94:Thread-19 95:Thread-19 96:Thread-11 97:Thread-19 98:Thread-11 99:Thread-19 
safeMap2:
0:Thread-29 1:Thread-27 2:Thread-28 3:Thread-25 4:Thread-27 5:Thread-25 6:Thread-27 7:Thread-25 8:Thread-24 9:Thread-20 10:Thread-20 11:Thread-20 12:Thread-20 13:Thread-20 14:Thread-20 15:Thread-20 16:Thread-20 17:Thread-20 18:Thread-20 19:Thread-20 20:Thread-20 21:Thread-20 22:Thread-20 23:Thread-20 24:Thread-20 25:Thread-20 26:Thread-20 27:Thread-20 28:Thread-20 29:Thread-20 30:Thread-20 31:Thread-20 32:Thread-20 33:Thread-20 34:Thread-20 35:Thread-20 36:Thread-20 37:Thread-20 38:Thread-20 39:Thread-20 40:Thread-20 41:Thread-20 42:Thread-20 43:Thread-20 44:Thread-20 45:Thread-20 46:Thread-20 47:Thread-20 48:Thread-20 49:Thread-20 50:Thread-20 51:Thread-20 52:Thread-20 53:Thread-20 54:Thread-20 55:Thread-20 56:Thread-20 57:Thread-20 58:Thread-20 59:Thread-20 60:Thread-20 61:Thread-20 62:Thread-20 63:Thread-20 64:Thread-20 65:Thread-20 66:Thread-20 67:Thread-20 68:Thread-20 69:Thread-20 70:Thread-20 71:Thread-20 72:Thread-20 73:Thread-20 74:Thread-20 75:Thread-20 76:Thread-20 77:Thread-20 78:Thread-20 79:Thread-20 80:Thread-20 81:Thread-20 82:Thread-20 83:Thread-20 84:Thread-20 85:Thread-20 86:Thread-20 87:Thread-20 88:Thread-20 89:Thread-20 90:Thread-20 91:Thread-20 92:Thread-20 93:Thread-20 94:Thread-20 95:Thread-20 96:Thread-20 97:Thread-20 98:Thread-20 99:Thread-20 
mapThread1.map.size() = 122
mapThread2.map.size() = 100
mapThread3.map.size() = 100

package queue;

import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;

public class QueueTest {

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

        //线程不安全
        Deque<String> unsafeQueue = new ArrayDeque<String>();
        //线程安全
        ConcurrentLinkedDeque<String> safeQueue1 = new ConcurrentLinkedDeque<String>();

        ArrayBlockingQueue<String> safeQueue2 = new ArrayBlockingQueue<String>(100);

        QueueThread t1 = new QueueThread(unsafeQueue);
        QueueThread t2 = new QueueThread(safeQueue1);
        QueueThread t3 = new QueueThread(safeQueue2);

        for(int i = 0; i < 10; i++){
            Thread thread1 = new Thread(t1, String.valueOf(i));
            thread1.start();
        }
        for(int i = 0; i < 10; i++) {
            Thread thread2 = new Thread(t2, String.valueOf(i));
            thread2.start();
        }
        for(int i = 0; i < 10; i++) {
            Thread thread3 = new Thread(t3, String.valueOf(i));
            thread3.start();
        }

        //等待子线程执行完
        Thread.sleep(2000);
 
        System.out.println("queueThread1.queue.size() = " + t1.queue.size());
        System.out.println("queueThread2.queue.size() = " + t2.queue.size());
        System.out.println("queueThread3.queue.size() = " + t3.queue.size());

        //输出queue中的值
        System.out.println("unsafeQueue:");
        for(String s:t1.queue)
        {
        	System.out.print(s + " ");
        }
        System.out.println();
        System.out.println("safeQueue1:");
        for(String s:t2.queue)
        {
        	System.out.print(s + " ");
        }
        System.out.println();
        System.out.println("safeQueue2:");
        for(String s:t3.queue)
        {
        	System.out.print(s + " ");
        }
    }
}

class QueueThread implements Runnable{
	public Queue<String> queue;

    public QueueThread(Queue<String> queue){
        this.queue = queue;
    }

    @Override
    public void run() {
    	int i = 0;
    	while(i<10)
    	{
    		i++;
    		try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            //把当前线程名称加入list中
            queue.add(Thread.currentThread().getName());
    	}        
    }
}
输出:
queueThread1.queue.size() = 93
queueThread2.queue.size() = 100
queueThread3.queue.size() = 100
unsafeQueue:
6 0 2 9 8 4 5 6 7 3 0 2 9 7 6 5 8 3 2 1 0 8 5 4 6 7 1 3 0 2 9 7 4 5 8 1 3 0 9 8 5 4 7 6 1 3 2 0 9 8 5 4 7 6 1 0 2 9 6 7 4 5 8 1 2 3 0 9 8 5 4 7 6 1 2 3 0 9 6 7 4 5 8 1 3 2 0 9 8 5 4 7 6 
safeQueue1:
0 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 1 2 0 2 0 1 3 4 5 6 7 9 8 8 9 7 5 6 4 3 1 0 2 0 2 3 1 4 6 5 7 9 8 0 2 3 1 4 6 5 7 9 8 8 9 5 7 6 4 1 3 2 0 2 0 3 1 4 6 7 5 9 8 8 9 5 7 4 1 3 0 2 6 2 0 3 1 4 7 5 9 8 6 
safeQueue2:
1 2 3 4 6 5 0 9 7 8 7 8 9 0 5 6 4 3 2 1 1 2 4 6 5 0 8 9 7 3 5 3 0 7 9 8 6 4 2 1 3 0 5 1 2 4 6 8 9 7 0 5 3 1 2 4 6 8 9 7 9 8 3 0 6 5 4 7 2 1 5 0 8 9 3 1 2 7 4 6 3 8 9 0 5 6 4 7 2 1 0 9 5 8 3 1 2 7 6 4 

参考中国大学mooc网《Java核心技术》

发布了55 篇原创文章 · 获赞 17 · 访问量 5001

猜你喜欢

转载自blog.csdn.net/weixin_43698704/article/details/104078697