`

并发编程回顾:线程创建与线程池

 
阅读更多

原先多线程并发编程的学习笔记和代码整理一下贴上来。

---------------------------------

线程创建与线程池

一、线程创建

创建一个线程的方式有2种,一种是直接重写Thread类的run方法,另一种是实现Runnable接口重写run方法,然后传入Thread构造函数的方式启动。

1、直接使用Thread方式:

class InnerThreadTask{
	private Thread t;
	private String name;
	private int i=5;//每个线程执行5次
	public InnerThreadTask(String name){
		this.name=name;
	}
	public void runTask(){
		t=new Thread(name){//匿名内部类继承Thread类
			public void run(){//重写run方法
				while(true){
					System.out.println("name="+this.getName()+" i="+i);
					if(--i==0)return;
				}
			}
		};
		t.start();//启动
	}
}

然后执行new InnerThreadTask("InnerThread").runTask();即可启动线程。

2、实现Runnable接口方式:

class InnerRunnableTask{
	private Thread t;
	private String name;
	private int i=3;//每个线程执行3次
	public InnerRunnableTask(String name){
		this.name=name;
	}
	public void runTask(){//匿名内部类实现Runnable接口
		t=new Thread(new Runnable(){//new Thread(Runnable r,String name);
			public void run(){//重写run方法
				while(true){
					System.out.println("name="+Thread.currentThread().getName()+" i="+i);
					if(--i==0)return;
				}
			}
		},name);
		t.start();//启动
	}
}

然后执行new InnerRunnableTask("InnerRunnable").runTask();即可启动线程。

二、线程池

JavaSE5新增的java.util.concurrent包中的Executors类提供了几种线程池,使得创建和管理线程更加方便。

1、CachedThreadPool:

JDK文档:创建一个根据需要创建新线程的线程池,但在以前构造的线程可用时将重用它们。

意思就是线程池内的线程可以被复用。

举例:先定义一个task。

class CachedTask implements Runnable{
	private int i=10;//每个线程执行10次
	public void run(){
		while(true){
                        System.out.println("ThreadName="+Thread.currentThread().getName()+" i=" + i);
			if(--i==0) return;
		}
	}
}

打印10遍线程名。

创建CachedThreadPool:

ExecutorService exec=Executors.newCachedThreadPool();
for(int i=10;i>0;i--){
    exec.execute(new CachedTask());//执行给定的线程。
}
exec.shutdown();

此处使用Executors类创建出CachedThreadPool线程池,同时执行10个线程,每个线程执行10次。

exec.shutdown();关闭线程池,防止新任务被提交。但会继续执行shutdown以前提交的全部任务,且不接受新任务。

2、FixedThreadPool:

JDK文档:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。

意思就是可以限制线程池内线程数的个数,如果任务数超过了线程数,后面的任务就会以队列的方式来等待。

举例:同样先定义一个task:

class FixedTask implements Runnable{
	private int i=1;
	public void run(){
		while(true){
			System.out.println("ThreadName="+Thread.currentThread().getName()+" i=" + i);
			if(--i==0) return;
		}
	}
}

每个线程打印1遍线程名。

创建FixedThreadPool:

ExecutorService exec = Executors.newFixedThreadPool(5);
for(int i=10;i>0;i--){
	exec.execute(new FixedTask());
}

注意,此处限定了线程数最大为5,同时执行10个任务。如果前5个任务没有执行完,则后面的任务会一直等待到有可用的线程。

3、SingleThreadExecutor:

JDK文档:创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程。

SingleThreadExecutor是只有单个线程的执行器,可以理解为线程数量为1的FixedThreadPool。

可以把SingleThreadExecutor当做一个FIFO队列来使用。

举例:定义task

class SingleTask implements Runnable{
	private int i=10;
	public void run(){
		while(true){
			System.out.println("ThreadName="+Thread.currentThread().getName()+" i=" + i);
			if(--i==0) return;
		}
	}
}

打印10遍线程名字。

创建SingleThreadExecutor:

ExecutorService exec = Executors.newSingleThreadExecutor();
for(int i=5;i>0;i--){
	exec.execute(new SingleTask());
}

这里通过执行可以看出,在每个线程执行完后,才会执行下一个线程。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics