采用new Thread的方式产生多线程,可能有以下一些问题:
线程的创建和销毁开销很大,尤其是有些线程的存在时间较短;
线程的创建和销毁过程中伴随着CPU在线程间的切换,开销很大;
线程池的优点有:
减少了创建和销毁线程的次数,工作线程可以一直重用。
在java中,每个线程都归属于某个ThreadGroup来管理。
首先看成员变量。
/**
* {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
* This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
* @see Thread
*/
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
// Name of this ThreadGroup
// VM needs this field name for debugging.
private String name;
// Maximum priority for Threads inside this ThreadGroup
private int maxPriority = Thread.MAX_PRIORITY;
// The ThreadGroup to which this ThreadGroup belongs
// VM needs this field name for debugging.
final ThreadGroup parent;
/**
* Weak references to the threads in this group.
* Access is guarded by synchronizing on this field.
*/
private final List> threadRefs = new ArrayList>(5);
/**
* View of the threads.
* Access is guarded by synchronizing on threadRefs.
*/
private final Iterable threads = CollectionUtils.dereferenceIterable(threadRefs, true);
/**
* Thread groups. Access is guarded by synchronizing on this field.
*/
private final List groups = new ArrayList(3);
// Whether this ThreadGroup is a daemon ThreadGroup or not
private boolean isDaemon;
// Whether this ThreadGroup has already been destroyed or not
private boolean isDestroyed;
/* the VM uses these directly; do not rename */
**static final ThreadGroup systemThreadGroup = new ThreadGroup();
static final ThreadGroup mainThreadGroup = new ThreadGroup(systemThreadGroup, "main");**
……省略代码……
}
ThreadGroup中采用弱引用的链表方式,可以添加Thread(链表默认容量为5)。同时有一个ThreadGroup本身也可以通过链表方式组织其他的ThreadGroup(链表默认容量为3)。
另外,这里定义了一个main类型的ThreadGroup。也就是说,在主线程的线程组的名字就是“main”。例如:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String name=Thread.currentThread().getThreadGroup().getName();
System.out.println(name);
}
}
下面来看ThreadGroup的3构造函数。
/**
* {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
* This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
* @see Thread
*/
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
……省略代码……
/**
* Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup}
* will be child of the {@code ThreadGroup} to which the calling thread belongs.
*
* @param name the name
* @see Thread#currentThread
*/
public ThreadGroup(String name) {
this(Thread.currentThread().getThreadGroup(), name);
}
/**
* Constructs a new {@code ThreadGroup} with the given name, as a child of the
* given {@code ThreadGroup}.
*
* @param parent the parent
* @param name the name
* @throws NullPointerException if {@code parent == null}
* @throws IllegalThreadStateException if {@code parent} has been
* destroyed already
*/
public ThreadGroup(ThreadGroup parent, String name) {
if (parent == null) {
throw new NullPointerException("parent == null");
}
this.name = name;
this.parent = parent;
if (parent != null) {
parent.add(this);
this.setMaxPriority(parent.getMaxPriority());
if (parent.isDaemon()) {
this.setDaemon(true);
}
}
}
/**
* Initialize the special "system" ThreadGroup. Was "main" in Harmony,
* but we have an additional group above that in Android.
*/
private ThreadGroup() {
this.name = "system";
this.parent = null;
}
……省略代码……
}
如果是完全无参数的构造函数,表明这个ThreadGroup没有parent,否则parent就是生成ThreadGroup的当前线程的线程组。这样,ThreadGroup就可以形成一棵树。
继续查看ThreadGroup的关键方法。
/**
* {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
* This class is obsolete. See Effective Java Item 73, "Avoid thread groups" for details.
* @see Thread
*/
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
……省略代码……
/**
* Returns the number of running {@code Thread}s which are children of this thread group,
* directly or indirectly.
*
* @return the number of children
*/
public int activeCount() {
int count = 0;
synchronized (threadRefs) {
for (Thread thread : threads) {
if (thread.isAlive()) {
count++;
}
}
}
synchronized (groups) {
for (ThreadGroup group : groups) {
count += group.activeCount();
}
}
return count;
}
/**
* Interrupts every {@code Thread} in this group and recursively in all its
* subgroups.
*
* @see Thread#interrupt
*/
public final void interrupt() {
synchronized (threadRefs) {
for (Thread thread : threads) {
thread.interrupt();
}
}
synchronized (groups) {
for (ThreadGroup group : groups) {
group.interrupt();
}
}
}
……省略代码……
}
由于一个ThreadGroup中的Thread是由链表方式组织的弱引用类型,activeCount()可以返回当前还有效的Thread。interrupt()函数让一个ThreadGroup中所有的Thread都中断。
这里主要分析与ThreadGroup相关的内容。
首先看Thread的9个构造函数。
/**
* Constructs a new {@code Thread} with no {@code Runnable} object and a
* newly generated name. The new {@code Thread} will belong to the same
* {@code ThreadGroup} as the {@code Thread} calling this constructor.
*
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread() {
create(null, null, null, 0);
}
/**
* Constructs a new {@code Thread} with a {@code Runnable} object and a
* newly generated name. The new {@code Thread} will belong to the same
* {@code ThreadGroup} as the {@code Thread} calling this constructor.
*
* @param runnable
* a {@code Runnable} whose method run
will be
* executed by the new {@code Thread}
*
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(Runnable runnable) {
create(null, runnable, null, 0);
}
/**
* Constructs a new {@code Thread} with a {@code Runnable} object and name
* provided. The new {@code Thread} will belong to the same {@code
* ThreadGroup} as the {@code Thread} calling this constructor.
*
* @param runnable
* a {@code Runnable} whose method run
will be
* executed by the new {@code Thread}
* @param threadName
* the name for the {@code Thread} being created
*
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(Runnable runnable, String threadName) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(null, runnable, threadName, 0);
}
/**
* Constructs a new {@code Thread} with no {@code Runnable} object and the
* name provided. The new {@code Thread} will belong to the same {@code
* ThreadGroup} as the {@code Thread} calling this constructor.
*
* @param threadName
* the name for the {@code Thread} being created
*
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*
*/
public Thread(String threadName) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(null, null, threadName, 0);
}
/**
* Constructs a new {@code Thread} with a {@code Runnable} object and a
* newly generated name. The new {@code Thread} will belong to the {@code
* ThreadGroup} passed as parameter.
*
* @param group
* {@code ThreadGroup} to which the new {@code Thread} will
* belong
* @param runnable
* a {@code Runnable} whose method run
will be
* executed by the new {@code Thread}
* @throws IllegalThreadStateException
* if group.destroy()
has already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(ThreadGroup group, Runnable runnable) {
create(group, runnable, null, 0);
}
/**
* Constructs a new {@code Thread} with a {@code Runnable} object, the given
* name and belonging to the {@code ThreadGroup} passed as parameter.
*
* @param group
* ThreadGroup to which the new {@code Thread} will belong
* @param runnable
* a {@code Runnable} whose method run
will be
* executed by the new {@code Thread}
* @param threadName
* the name for the {@code Thread} being created
* @throws IllegalThreadStateException
* if group.destroy()
has already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(ThreadGroup group, Runnable runnable, String threadName) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(group, runnable, threadName, 0);
}
/**
* Constructs a new {@code Thread} with no {@code Runnable} object, the
* given name and belonging to the {@code ThreadGroup} passed as parameter.
*
* @param group
* {@code ThreadGroup} to which the new {@code Thread} will belong
* @param threadName
* the name for the {@code Thread} being created
* @throws IllegalThreadStateException
* if group.destroy()
has already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(ThreadGroup group, String threadName) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(group, null, threadName, 0);
}
/**
* Constructs a new {@code Thread} with a {@code Runnable} object, the given
* name and belonging to the {@code ThreadGroup} passed as parameter.
*
* @param group
* {@code ThreadGroup} to which the new {@code Thread} will
* belong
* @param runnable
* a {@code Runnable} whose method run
will be
* executed by the new {@code Thread}
* @param threadName
* the name for the {@code Thread} being created
* @param stackSize
* a stack size for the new {@code Thread}. This has a highly
* platform-dependent interpretation. It may even be ignored
* completely.
* @throws IllegalThreadStateException
* if group.destroy()
has already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
if (threadName == null) {
throw new NullPointerException("threadName == null");
}
create(group, runnable, threadName, stackSize);
}
/**
* Package-scope method invoked by Dalvik VM to create "internal"
* threads or attach threads created externally.
*
* Don't call Thread.currentThread(), since there may not be such
* a thing (e.g. for Main).
*/
Thread(ThreadGroup group, String name, int priority, boolean daemon) {
synchronized (Thread.class) {
id = ++Thread.count;
}
if (name == null) {
this.name = "Thread-" + id;
} else {
this.name = name;
}
if (group == null) {
throw new InternalError("group == null");
}
this.group = group;
this.target = null;
this.stackSize = 0;
this.priority = priority;
this.daemon = daemon;
/* add ourselves to our ThreadGroup of choice */
this.group.addThread(this);
}
可以看出,create(group, runnable, threadName, stackSize)是关键方法。
/**
* Initializes a new, existing Thread object with a runnable object,
* the given name and belonging to the ThreadGroup passed as parameter.
* This is the method that the several public constructors delegate their
* work to.
*
* @param group ThreadGroup to which the new Thread will belong
* @param runnable a java.lang.Runnable whose method run
will
* be executed by the new Thread
* @param threadName Name for the Thread being created
* @param stackSize Platform dependent stack size
* @throws IllegalThreadStateException if group.destroy()
has
* already been done
* @see java.lang.ThreadGroup
* @see java.lang.Runnable
*/
private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
Thread currentThread = Thread.currentThread();
if (group == null) {
group = currentThread.getThreadGroup();//当前线程的线程组
}
if (group.isDestroyed()) {
throw new IllegalThreadStateException("Group already destroyed");
}
this.group = group;
synchronized (Thread.class) {
id = ++Thread.count;
}
if (threadName == null) {
this.name = "Thread-" + id;
} else {
this.name = threadName;
}
this.target = runnable;
this.stackSize = stackSize;
this.priority = currentThread.getPriority();
this.contextClassLoader = currentThread.contextClassLoader;
// Transfer over InheritableThreadLocals.
if (currentThread.inheritableValues != null) {
inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
}
// add ourselves to our ThreadGroup of choice
this.group.addThread(this);
}
可以看出,Thread构造函数中ThreadGroup为null,或者不包含ThreaGroup参数时,Thread都会被加入到当前线程的ThreadGroup中。
线程池可以理解为其中有多个固定的工作线程,然后不断从同一个任务队列中取得任务并执行。如果某线程取任务时没有任务,该线程处于wait()状态;当添加任务时,notiyfy()一次通知最近的处于wait()状态的线程。这符合一个生产者,多个消费者的模型。
这里参考《Java网络编程精解(孙卫琴)》P67的内容来编写自定义的ThreadPool。
public class ThreadPool extends ThreadGroup{
private boolean isClosed=false;
private LinkedList workQueue;//任务队列
private static int threadPoolID;
private int threadID;
public ThreadPool(int poolSize) {
// TODO Auto-generated constructor stub
super("ThreadPool"+(threadPoolID++));
setDaemon(true);
workQueue=new LinkedList();
for (int i = 0; i < poolSize; i++) {
new WorkThread().start();//启用固定数量的线程
}
}
public synchronized void execute(Runnable task){
if (isClosed) {
throw new IllegalStateException();
}
if (task!=null) {
workQueue.add(task);
notify();//唤醒一个wait()的线程
}
}
/**
* 通过interrupt()来通知线程组中所有的线程执行中断
* */
public synchronized void close(){
if (!isClosed) {
isClosed=true;
workQueue.clear();
interrupt();//中断所有线程
}
}
public void join(){
synchronized (this) {
isClosed=true;//任务取得为null
notifyAll();//唤醒所有线程
}
Thread[] threads=new Thread[activeCount()];
int count=enumerate(threads);
for (int i = 0; i < count; i++) {
try {
threads[i].join();//
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected synchronized Runnable getTask() throws InterruptedException{
while (workQueue.size()==0) {
if (isClosed) return null;
wait();
}
return workQueue.removeFirst();
}
private class WorkThread extends Thread{
public WorkThread() {
// TODO Auto-generated constructor stub
super(ThreadPool.this,"WokrThread-"+(threadID++));
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
while (!isInterrupted()) {
Runnable task=null;
try {
task=getTask();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (task==null) {
return;
}
task.run();
}
}
}
}
这里进行测试。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadPool pool=new ThreadPool(3);
for (int i = 0; i < 10; i++) {
pool.execute(createTask(i));
}
pool.join();//执行完正在执行的任务再结束
// pool.close();//立即结束
}
private static Runnable createTask(final int taskID){
return new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Task"+taskID+":start");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Task"+taskID+":end");
}
}
};
}
}
真正实现的线程池类有3个。
(1) ThreadPoolExecutor
采用几个线程来执行提交的任务。其中一个构造函数如下:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)
API参数如下:
corePoolSize :the number of threads to keep in the pool, even if they are idle, unless allowCoreThreadTimeOut is set
maximumPoolSize :the maximum number of threads to allow in the pool
keepAliveTime :when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating.
unit the time:unit for the keepAliveTime argument
workQueue :the queue to use for holding tasks before they are executed. This queue will hold only the Runnable tasks submitted by the execute method.
最常用的场景是通过Executors类的工厂方法来构造,包括newCachedThreadPool()、newFixedThreadPool(int) 、newSingleThreadExecutor() ,具体查看下一节。
(2) ScheduledThreadPoolExecutor
任务可以在一定时间后执行,也可以设置周期性执行。构造函数比较简单,只需要指定线程数量。主要方法在schedule相关的成员方法。例如:
public ScheduledFuture> scheduleWithFixedDelay (Runnable command, long initialDelay, long delay, TimeUnit unit)
API参数如下:
command:the task to execute
initialDelay :the time to delay first execution
delay :the delay between the termination of one execution and the commencement of the next
unit the time:unit of the initialDelay and delay parameters
返回值:
a ScheduledFuture representing pending completion of the task, and whose get() method will throw an exception upon cancellation
最常用的场景是通过Executors类的工厂方法来构造,包括newCachedThreadPool()、newFixedThreadPool(int) 、newSingleThreadExecutor() ,具体查看下一节。
(3) ForkJoinPool
Fork/Join模式的线程池,用于支持并行计算。更多的信息来源于JDK 7 中的 Fork/Join 模式。
一般来讲,不直接初始化线程池对象。Executors中几个静态方法提供了线程池的实例化方法。
(1)只有一个工作线程的线程池(ThreadPoolExecutor)
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue. (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue()));
}
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
* equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
* @param threadFactory the factory to use when creating new
* threads
*
* @return the newly created single-threaded Executor
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
threadFactory));
}
(2)固定线程数量(ThreadPoolExecutor)
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
* at most {@code nThreads} threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
* execution prior to shutdown, a new one will take its place if
* needed to execute subsequent tasks. The threads in the pool will
* exist until it is explicitly {@link ExecutorService#shutdown
* shutdown}.
*
* @param nThreads the number of threads in the pool
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
threadFactory);
}
(3) 不固定数量的线程池(ThreadPoolExecutor)
如果线程不被使用,线程的存活时间为60s。
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue());
}
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available, and uses the provided
* ThreadFactory to create new threads when needed.
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue(),
threadFactory);
}
(4)Fork/Join模式的线程池(ForkJoinPool)
/**
* Creates a thread pool that maintains enough threads to support
* the given parallelism level, and may use multiple queues to
* reduce contention. The parallelism level corresponds to the
* maximum number of threads actively engaged in, or available to
* engage in, task processing. The actual number of threads may
* grow and shrink dynamically. A work-stealing pool makes no
* guarantees about the order in which submitted tasks are
* executed.
*
* @param parallelism the targeted parallelism level
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code parallelism <= 0}
* @since 1.8
* @hide
*/
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
/**
* Creates a work-stealing thread pool using all
* {@link Runtime#availableProcessors available processors}
* as its target parallelism level.
* @return the newly created thread pool
* @since 1.8
* @hide
*/
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
(5)单个线程的Scheduled类型线程池(ScheduledThreadPoolExecutor)
/**
* Creates a single-threaded executor that can schedule commands
* to run after a given delay, or to execute periodically.
* (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newScheduledThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
*/
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
/**
* Creates a single-threaded executor that can schedule commands
* to run after a given delay, or to execute periodically. (Note
* however that if this single thread terminates due to a failure
* during execution prior to shutdown, a new one will take its
* place if needed to execute subsequent tasks.) Tasks are
* guaranteed to execute sequentially, and no more than one task
* will be active at any given time. Unlike the otherwise
* equivalent {@code newScheduledThreadPool(1, threadFactory)}
* the returned executor is guaranteed not to be reconfigurable to
* use additional threads.
* @param threadFactory the factory to use when creating new
* threads
* @return a newly created scheduled executor
* @throws NullPointerException if threadFactory is null
*/
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1, threadFactory));
}
(6)多个线程的Scheduled类型线程池(ScheduledThreadPoolExecutor)
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @param threadFactory the factory to use when the executor
* creates a new thread
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws NullPointerException if threadFactory is null
*/
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
这里写了一个线程池的网络服务器。
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* created by CaoYanfeng
* 一个简单的服务器程序。采用线程池来并发处理Socket。
* */
public class NetworkService {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port,int poolSize) throws IOException {
// TODO Auto-generated constructor stub
serverSocket=new ServerSocket(port);
pool=Executors.newCachedThreadPool();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
final NetworkService service=new NetworkService(8000, 3);
service.run();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//关闭线程池
public void shutdownAndAwaitTermination(ExecutorService pool){
pool.shutdown();
pool.shutdownNow();
try {
if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
public void run(){
System.out.println("启动Service!");
while (true) {
try {
pool.execute(new Handler(serverSocket.accept()));
} catch (IOException e) {
// TODO Auto-generated catch block
pool.shutdown();
e.printStackTrace();
}
}
}
//socket处理的句柄
private class Handler implements Runnable{
private static final int BUFFER_SIZE=1024;
private final Socket socket;
private BufferedInputStream inputStream;
public Handler(Socket socket) {
// TODO Auto-generated constructor stub
this.socket=socket;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
inputStream=new BufferedInputStream(socket.getInputStream());
byte[] buffer=new byte[BUFFER_SIZE];
int validSize=0;
while (socket.isConnected()&&(validSize=inputStream.read(buffer))!=0) {
System.out.print(socket.getInetAddress()+":"+socket.getPort()+"---");
for (int i = 0; i < validSize; i++) {
System.out.print(buffer[i]+" ");
}
System.out.println();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
socket.close();
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
有时候将耗时任务委托给线程池后,当执行结束,需要获得任务执行后的结果,或者单纯判断执行完毕。这里有一个实例,采用的是Runable子类FutureTask来封装任务。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
/**
* created by 曹艳丰
* 2016-08-05
*采用FutureTask来返回线程执行完毕后的状态。
*这里是一个任务
* */
public class FutureTaskTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService service=Executors.newCachedThreadPool();
FutureTask futureTask=new FutureTask(new Callable() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(5000);
return "耗时操作-0结束!";
}
});
service.execute(futureTask);
try {
System.out.println(futureTask.get());//get()是一个阻塞函数
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
shutdownAndAwaitTermination(service);
}
//关闭线程池
public static void shutdownAndAwaitTermination(ExecutorService pool){
pool.shutdown();
pool.shutdownNow();
try {
if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
如果是多任务的话,ExecutorService有几个函数可以用来使用。
这里我写了一个例子。
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* created by CaoYanfeng
* 2016-08-05
*采用FutureTask来返回线程执行完毕后的状态。
*这里是多任务回调
* */
public class MutileFutureTaskTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ExecutorService service=Executors.newCachedThreadPool();
Callable task1=new Callable() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(2000);
return "耗时操作-1结束!";
}
};
Callable task2=new Callable() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(2000);
return "耗时操作-2结束!";
}
};
Callable task3=new Callable() {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
Thread.sleep(2000);
return "耗时操作-3结束!";
}
};
List> tasks=new ArrayList>();
tasks.add(task3);
tasks.add(task2);
tasks.add(task1);
try {
List> result=service.invokeAll(tasks);//阻塞函数,所有任务执行完毕后返回
for (Future future : result) {
try {
System.out.println(future.get());
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
shutdownAndAwaitTermination(service);
}
//关闭线程池
public static void shutdownAndAwaitTermination(ExecutorService pool){
pool.shutdown();
pool.shutdownNow();
try {
if (pool.awaitTermination(60, TimeUnit.MILLISECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}