原先多线程并发编程的学习笔记和代码整理一下贴上来。
---------------------------------
线程创建与线程池
一、线程创建
创建一个线程的方式有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());
}
这里通过执行可以看出,在每个线程执行完后,才会执行下一个线程。