java线程的通信和线程池

1.传统的线程通信

   使用synchronized修饰的同步方法或者同步代码块,则要在方法体重直接调用wait()、notify()和notifyAll()3个方法。其中:

   wait():使当前线程等待,知道其他线程调用该同步监视器的notify()或者notifyAll()方法。

   notify():唤醒在此同步监视器上等待的单个线程。

   notifyAll():唤醒在此同步监视器上等待的所有线程。

2.使用Condition控制线程通信

   如果程序中不使用synchronized关键字实现同步的话,而是直接使用Lock对象保证同步,则不能使用上述3个方法。一般使用Lock对象的newCondition()方法返回的Condition实例来控制同步通信。即使用Condition类的await()、signal()、signalAll()方法分别代替上述的3个方法。

3.使用阻塞队列(BlockingQueue)控制线程通信

  BlockingQueue是Queue的子接口,但当某个线程试图向BloockingQueue中放入元素时,如果队列已满,则该线程被阻塞,反之,若某个线程从队列中取元素且队列为空时,则该线程也会被阻塞。如下:

import java.util.concurrent.*;
class Producer extends Thread 
{
	private BlockingQueue bq;
	public Producer(BlockingQueue bq)
	{
		this.bq=bq;
	}
	@Override
	public void run()
	{
		String[] strArr=new String[]{"Java","讲义","Spring"};
		for(int i=0;i<33333;i++)
		{
			System.out.println(getName()+"生产者生产");
			try
			{
				Thread.sleep(200);
				bq.put(strArr[i%3]);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println(getName()+"生产完成:"+bq);
		}
	}
}
class Consumer extends Thread
{
	private BlockingQueue bq;
	public Consumer(BlockingQueue bq)
	{
		this.bq=bq;
	}
	@Override
	public void run()
	{
		while(true)
		{
			System.out.println(getName()+"消费者准备消费!");
			try
			{
				Thread.sleep(200);
				bq.take();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			System.out.println(getName()+"消费成功:"+bq);
		}
	}
}
public class BlockingQueueTest2 
{
	public static void main(String[] args) 
	{//程序中生产者和消费者依次执行
		//创建只有1个元素的阻塞队列
		BlockingQueue bq=new ArrayBlockingQueue<>(1);
		//启动3个生产者线程和1个消费者线程
		new Producer(bq).start();
		new Producer(bq).start();
		new Producer(bq).start();
		new Consumer(bq).start();
	}
}
4.线程池

  由于系统启动一个新线程的成本是比较高的,使用线程池可以在系统启动时就创建大量的空闲线程,并且线程池可以有效控制系统中并发执行的线程数,使系统保持高效的性能。使用方法如下:

import java.util.concurrent.*;
class MyThread implements Runnable 
{//使用Runnable接口定义一个简单的线程类
	public void run()
	{
		for(int i=0;i<100;i++)
		{
			System.out.println(Thread.currentThread().getName()+"i的值为:"+i);
		}
	}
	public static void main(String[] args) 
	{
		//创建一个固定数量的线程池
		ExecutorService pool=Executors.newFixedThreadPool(6);
		//向线程池中添加2个线程
		pool.submit(new MyThread());
		pool.submit(new MyThread());
		pool.shutdown();//关闭线程池
	}
}

  使用线程池计算多个分解的任务:

import java.util.concurrent.*;
import java.util.*;
class CalTask extends RecursiveTask 
{//使用多个线程实现累加和的功能
	//定义最多累加20个数
	private static final int THREADHOLD=20;
	private int arr[];//累加元素
	private int start;//开始位置
	private int end;//结束位置
	public CalTask(int[] arr,int start,int end)
	{
		this.arr=arr;
		this.start=start;
		this.end=end;
	}
	@Override
	protected Integer compute()
	{//线程执行函数
		int sum=0;
		if(end-start future=pool.submit(new CalTask(arr,0,arr.length));
		//获取最终的返回值
		System.out.println(future.get());
		pool.shutdown();
	}
}


你可能感兴趣的:(Java)