多线程

1.线程池

线程池可以避免执行多个线程的时候不断的创建新线程,可以节省时间,主要的线程池有CachedThreadPool,FixedThreadPool,SingleThreadExecutor,ScheduledThreadPool,使用方法都是相似的:
public class SysoutRunable implements Runnable{

	private int i;
	public SysoutRunable(int i) {
		this.i = i;
	}
	@Override
	public void run() {
		System.out.print(i + " ");
	}
}
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		for(int i = 0;i < 10;i++){
			newCachedThreadPool.execute(new SysoutRunable(i));
		}
		
		ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
		for(int i = 0;i < 10;i++){
			newFixedThreadPool.execute(new SysoutRunable(i));
		}
		ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
		for(int i = 0;i < 10;i++){
			newSingleThreadExecutor.execute(new SysoutRunable(i));
		}
		ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);
		for(int i = 0;i < 10;i++){
			newScheduledThreadPool.execute(new SysoutRunable(i));
			newScheduledThreadPool.schedule(new SysoutRunable(0), 5, TimeUnit.SECONDS);
		}
		newScheduledThreadPool.schedule(() -> { System.out.println("haha"); }, 1, TimeUnit.MINUTES);
输出如下:
0 3 4 7 8 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 2 1 5 9 6 0 1 2 3 4 5 6 7 8 9 haha

2.多线程返回值


多线程的Runnable不能返回值,要返回值可以采用Callable接口:
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		Future result = newCachedThreadPool.submit(() -> {return "codog";});
		try {
			System.out.println(result.get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
好像没看出是Callable接口,换一个如下:
		String str = newCachedThreadPool.submit(new Callable() {
			@Override
			public String call() throws Exception {
				return "www.codog.com.cn";
			}	
		}).get();
		System.out.println(str);
输出如下:
www.codog.com.cn

3.后台线程


后台线程会在所有非后台线程结束后结束,可以根据ThreadFactory定制线程池:
		ExecutorService newCachedThreadPool = Executors
				.newCachedThreadPool((r) -> {
					Thread t = new Thread(r);
					t.setDaemon(true);
					return t;
				});
		for (int i = 0; i < 10; i++) {
			newCachedThreadPool.execute(() -> {
				System.out.println(Thread.currentThread() + " : "
						+ Thread.currentThread().isDaemon());
			});
		}
输出如下:
Thread[Thread-0,5,main] : true

4.join和interrupt


join是指一个线程A调用join加入另一个线程B,知道A结束再继续执行B下面的内容,interrupt方法可以中断这一行为。
public class InnerThread extends Thread{

	@Override
	public void run() {
		System.out.println("内部线程正在运行");
	}

}
new OuterThread().start();

当代码如下的时候:
public class OuterThread extends Thread{

	private InnerThread innerThread = new InnerThread();
	@Override
	public void run() {
		System.out.println("外部线程开始执行");
		//innerThread.join();
		innerThread.start();
		//innerThread.join();
		System.out.println("外部线程结束执行");
	}

}

输出如下:
外部线程开始执行
外部线程结束执行
内部线程正在运行

当代码如下的时候:
public class OuterThread extends Thread{

	private InnerThread innerThread = new InnerThread();
	@Override
	public void run() {
		System.out.println("外部线程开始执行");
		//innerThread.join();
		innerThread.start();
		try {
			innerThread.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("外部线程结束执行");
	}

}

输出如下:
外部线程开始执行
内部线程正在运行
外部线程结束执行
看完了有没有感觉我是在欺骗你,多线程怎么表现的这么乖

5.原子类

原子类是指多线程操作下还是同步的状态的基础类,比如AtomicInteger,AtomicLong,AtomicReference等。
代码如下:
public class OperateClass {

	private int a = 0;
	private AtomicInteger ai = new AtomicInteger(0);

	public void increment() {
		a++;
		ai.addAndGet(1);
	}

	public int getA() {
		return a;
	}

	public void setA(int a) {
		this.a = a;
	}

	public AtomicInteger getAi() {
		return ai;
	}

	public void setAi(AtomicInteger ai) {
		this.ai = ai;
	}
}
public class OperateThread implements Runnable{

	private OperateClass operateClass;
	
	public OperateThread(OperateClass operateClass) {
		super();
		this.operateClass = operateClass;
	}

	@Override
	public void run() {
		operateClass.increment();
	}
}
		OperateClass opc = new OperateClass();
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		for(int i = 0;i < 1000;i++){
			newCachedThreadPool.execute(new OperateThread(opc));
		}
		newCachedThreadPool.shutdown();
		System.out.println("a:" + opc.getA() + ",ai: " + opc.getAi());
输出如下:
a:994,ai: 1000
可以看出同样是加了1000次,但是原子类是可以在多线程环境下工作的。
原子类包中还有很多可以参考,但是到需要的时候自然会用到。

6.同步队列实现生产者和消费者

生产者和消费者的编程模型是很出名的,可以利用wait和notify来实现,但是代码的复杂度还是有的,而且可读性差,java内置的同步队列可以满足需求,为了说明问题,我还增加了一个搬运者的角色,生产者负责生产,搬运者负责搬运生产者产生的产品,消费者负责消费搬运者搬运的产品,代码如下:
public abstract class Person {

	protected LinkedBlockingQueue productions;

	protected LinkedBlockingQueue targetProductions;

	public Person(LinkedBlockingQueue productions,
			LinkedBlockingQueue targetProductions) {
		super();
		this.productions = productions;
		this.targetProductions = targetProductions;
	}

	public LinkedBlockingQueue getProductions() {
		return productions;
	}

	public void setProductions(LinkedBlockingQueue productions) {
		this.productions = productions;
	}

	public LinkedBlockingQueue getTargetProductions() {
		return targetProductions;
	}

	public void setTargetProductions(
			LinkedBlockingQueue targetProductions) {
		this.targetProductions = targetProductions;
	}

	protected abstract void move() throws InterruptedException;
}

public class Production {

	private int id;

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

	public Production(int id) {
		super();
		this.setId(id);
	}

	public int getId() {
		return id;
	}

	@Override
	public String toString() {
		return "Production [id=" + id + "]";
	}

}

public class Producter extends Person implements Runnable {

	public Producter(LinkedBlockingQueue productions,
			LinkedBlockingQueue targetProductions) {
		super(productions, targetProductions);
	}

	@Override
	public void run() {
		for(int i = 0;i < 10;i++){
			try {
				move();
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	protected void move() throws InterruptedException {
		if(targetProductions == null){
			System.out.println("生产者的目标队列不能为空");
			return;
		}
		int id = (int)(Math.random() * 100);
		Production production = new Production(id);
		targetProductions.put(production);
		System.out.println("生产了" + production.toString());
	}

}

public class Mover extends Person implements Runnable{

	public Mover(LinkedBlockingQueue productions,
			LinkedBlockingQueue targetProductions) {
		super(productions, targetProductions);
	}

	@Override
	public void run() {
		while(true){
			try {
				move();
				Thread.sleep(35);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	protected void move() throws InterruptedException {
		if(targetProductions == null || productions == null){
			System.out.println("搬运者的源队列和目标队列都不能为空");
			return;
		}
		Production production = productions.take();
		targetProductions.put(production);
		System.out.println("移动了" + production.toString());
	}

	
}

public class Consumer extends Person implements Runnable{

	public Consumer(LinkedBlockingQueue productions,
			LinkedBlockingQueue targetProductions) {
		super(productions, targetProductions);
	}

	@Override
	public void run() {
		while(true){
			try {
				move();
				Thread.sleep(31);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	protected void move() throws InterruptedException {
		if(productions == null){
			System.out.println("消费者的源队列不能为空");
			return;
		}
		System.out.println("消费了" + productions.take().toString());		
	}

}
	public static void main(String[] args) {
		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		LinkedBlockingQueue productions = new LinkedBlockingQueue<>();
		LinkedBlockingQueue targetProductions = new LinkedBlockingQueue<>();
		newCachedThreadPool.execute(new Producter(null, productions));
		newCachedThreadPool.execute(new Mover(productions, targetProductions));
		newCachedThreadPool.execute(new Consumer(targetProductions, null));
	}
输出如下:
生产了Production [id=65]
移动了Production [id=65]
消费了Production [id=65]
生产了Production [id=19]
生产了Production [id=44]
生产了Production [id=76]
移动了Production [id=19]
消费了Production [id=19]
生产了Production [id=2]
生产了Production [id=6]
生产了Production [id=12]
生产了Production [id=40]
移动了Production [id=44]
消费了Production [id=44]
生产了Production [id=54]
生产了Production [id=3]
移动了Production [id=76]
消费了Production [id=76]
移动了Production [id=2]
消费了Production [id=2]
移动了Production [id=6]
消费了Production [id=6]
移动了Production [id=12]
消费了Production [id=12]
移动了Production [id=40]
消费了Production [id=40]
移动了Production [id=54]
消费了Production [id=54]
移动了Production [id=3]
消费了Production [id=3]

相关内容:
前言
对象和类型
操作符和引用
流程控制语句
初始化和清理
访问控制
组合和继承
接口和多态
接口与抽象类
容器
异常
类型信息
泛型
数组
IO系统
枚举类型
注解
多线程
总结