相关代码:
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++){
exec.execute(new LiftOff());
System.out.println("");
}
exec.shutdown();
}
}
Executor在java 5/6中是启动任务(线程)的优选方法;
主要类描述:
1.
public interface ExecutorService
extends Executor
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
An ExecutorService can be shut down, which will cause it to stop accepting new tasks. After being shut down, the executor will eventually terminate, at which point no tasks are actively executing, no tasks are awaiting execution, and no new tasks can be submitted.
(1)void execute(Runnable command)
Executes the given command at some time in the future.
这个是从Executor接口中继承的方法
(2)shutdown
void shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
调用该方法之后,将不会接受新的线程对象,原来的线程对象将会执行完毕。
(3)
awaitTermination
boolean awaitTermination(long timeout,
TimeUnit unit)
throws InterruptedException
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
Parameters:
timeout - the maximum time to wait
unit - the time unit of the timeout argument
Returns:
true if this executor terminated and false if the timeout elapsed before termination
如果所有的任务在规定的时间到达之前全部结束,则返回true。否则返回false。
2.
java.lang.Object
extended by java.util.concurrent.Executors
public class Executors
extends Object
(1)newCachedThreadPool
public static ExecutorService newCachedThreadPool()
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 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 ThreadPoolExecutor constructors.
Returns:
the newly created thread pool
该方法通常会创建与所需数量相同的线程。在回收旧线程时,不会创建新的线程,这个方法是首选。当这个方法不能满足需要时,才考虑使用其他方法。
(2)
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads)
Creates a thread pool that reuses a fixed set of threads operating off a shared unbounded queue. 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.
Parameters:
nThreads - the number of threads in the pool
Returns:
the newly created thread pool
该方法是创建一个含有固定数量线程的线程池
(3)
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor()
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 newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
如果向它提交了多个任务,那么这些任务将排队,每个任务都会在下一个任务开始之前运行结束,所有任务将使用相同的线程。即,它会序列化所有提交给它的任务。
3
extended by java.util.concurrent.locks.ReentrantLock
public class ReentrantLock
extends Object
implements Lock, Serializable
A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.
A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread. The method will return immediately if the current thread already owns the lock. This can be checked using methods isHeldByCurrentThread(), and getHoldCount().
(1)
lock
public void lock()
Acquires the lock.
Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.
If the current thread already holds the lock then the hold count is incremented by one and the method returns immediately.
If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired, at which time the lock hold count is set to one.
(2)
unlock
public void unlock()
Attempts to release this lock.
If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.
例如:
public static int m=0;
private static Lock lock = new ReentrantLock();
public static int getI(){
lock.lock();
try{
m++;
m++;
return m;
}finally{
lock.unlock();
}
}
注意:return 要放到try块中,unlock方法要放到finally块中。如果在使用synchronized失败了,那么就会抛出一个异常,但是没有机会做任何清理工作。lock就可以做到。
(3)
tryLock
public boolean tryLock()
Acquires the lock only if it is not held by another thread at the time of invocation.
Acquires the lock if it is not held by another thread and returns immediately with the value true, setting the lock hold count to one. Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This "barging" behavior can be useful in certain circumstances, even though it breaks fairness. If you want to honor the fairness setting for this lock, then use tryLock(0, TimeUnit.SECONDS) which is almost equivalent (it also detects interruption).
If the current thread already holds this lock then the hold count is incremented by one and the method returns true.
If the lock is held by another thread then this method will return immediately with the value false.
Specified by:
tryLock in interface Lock
Returns:
true if the lock was free and was acquired by the current thread, or the lock was already held by the current thread; and false otherwise.
这个方法是抢先获得锁。有个缺点,如果其他线程已经获得锁,那么它放回false后,继续执行下面的代码,达不到同步的作用,还是用lock吧
(4)
tryLock
public boolean tryLock(long timeout,
TimeUnit unit)
throws InterruptedException
Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.
Acquires the lock if it is not held by another thread and returns immediately with the value true, setting the lock hold count to one. If this lock has been set to use a fair ordering policy then an available lock will not be acquired if any other threads are waiting for the lock. This is in contrast to the tryLock() method. If you want a timed tryLock that does permit barging on a fair lock then combine the timed and un-timed forms together:
if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
该方法的意思是在给定的时间内,去公平竞争锁。如果时间到还没有获得锁,则返回false。和synchronized不同,如果访问对象的某个synchronized方法,其它线程就不能访问该对象的所有synchronized方法。但是,如果没有synchronized而是在方法内部用了lock,就不会出现这种现象,其它线程还可以访问该对象的其它内部还有lock的方法。例如:
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed() throws Exception {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): ");
Thread.sleep(5 * 1000);
System.out.println("时间已过");
} finally {
if (captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(6, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(10, TimeUnit.SECONDS): " + captured);
} finally {
if (captured) {
lock.unlock();
} else {
System.out.println("没有执行");
}
}
}
public void f() {
System.out.println("其他方法");
}
public static void main(String[] args) {
final AttemptLocking al = new AttemptLocking();
ExecutorService exec = Executors.newCachedThreadPool();
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
al.untimed();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
al.timed();
}
};
Runnable r3 = new Runnable() {
@Override
public void run() {
al.f();
}
};
exec.execute(r1);
exec.execute(r3);
exec.execute(r2);
exec.shutdown();
}
}
4.
java.util.concurrent
Interface Future<V>
public interface Future<V>
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.
Sample Usage (Note that the following classes are all made-up.)
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target) throws InterruptedException {
Future<String> future = executor.submit(new Callable<String>() {
public String call() { return searcher.search(target); }
});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}
相关方法:
(1)cancel
boolean cancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
Parameters:
mayInterruptIfRunning - true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete
Returns:
false if the task could not be cancelled, typically because it has already completed normally; true otherwise
5.如果希望完成任务时,能够返回一个值,那么可以实现Callable接口而不是Runnable接口。例如:
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "result of TaskWithResult " + id;
}
}
public class CallableDemo {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++)
results.add(exec.submit(new TaskWithResult(i)));
for(int i=0;i<10;i++){
System.out.println("hahah"+i);
}
for (Future<String> fs : results)
try {
// get() blocks until completion:
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++){
exec.execute(new LiftOff());
System.out.println("");
}
exec.shutdown();
}
}
Executor在java 5/6中是启动任务(线程)的优选方法;
主要类描述:
1.
public interface ExecutorService
extends Executor
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
An ExecutorService can be shut down, which will cause it to stop accepting new tasks. After being shut down, the executor will eventually terminate, at which point no tasks are actively executing, no tasks are awaiting execution, and no new tasks can be submitted.
(1)void execute(Runnable command)
Executes the given command at some time in the future.
这个是从Executor接口中继承的方法
(2)shutdown
void shutdown()
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
调用该方法之后,将不会接受新的线程对象,原来的线程对象将会执行完毕。
(3)
awaitTermination
boolean awaitTermination(long timeout,
TimeUnit unit)
throws InterruptedException
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
Parameters:
timeout - the maximum time to wait
unit - the time unit of the timeout argument
Returns:
true if this executor terminated and false if the timeout elapsed before termination
如果所有的任务在规定的时间到达之前全部结束,则返回true。否则返回false。
2.
java.lang.Object
extended by java.util.concurrent.Executors
public class Executors
extends Object
(1)newCachedThreadPool
public static ExecutorService newCachedThreadPool()
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 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 ThreadPoolExecutor constructors.
Returns:
the newly created thread pool
该方法通常会创建与所需数量相同的线程。在回收旧线程时,不会创建新的线程,这个方法是首选。当这个方法不能满足需要时,才考虑使用其他方法。
(2)
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads)
Creates a thread pool that reuses a fixed set of threads operating off a shared unbounded queue. 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.
Parameters:
nThreads - the number of threads in the pool
Returns:
the newly created thread pool
该方法是创建一个含有固定数量线程的线程池
(3)
newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor()
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 newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
如果向它提交了多个任务,那么这些任务将排队,每个任务都会在下一个任务开始之前运行结束,所有任务将使用相同的线程。即,它会序列化所有提交给它的任务。
3
extended by java.util.concurrent.locks.ReentrantLock
public class ReentrantLock
extends Object
implements Lock, Serializable
A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.
A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread. The method will return immediately if the current thread already owns the lock. This can be checked using methods isHeldByCurrentThread(), and getHoldCount().
(1)
lock
public void lock()
Acquires the lock.
Acquires the lock if it is not held by another thread and returns immediately, setting the lock hold count to one.
If the current thread already holds the lock then the hold count is incremented by one and the method returns immediately.
If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until the lock has been acquired, at which time the lock hold count is set to one.
(2)
unlock
public void unlock()
Attempts to release this lock.
If the current thread is the holder of this lock then the hold count is decremented. If the hold count is now zero then the lock is released. If the current thread is not the holder of this lock then IllegalMonitorStateException is thrown.
例如:
public static int m=0;
private static Lock lock = new ReentrantLock();
public static int getI(){
lock.lock();
try{
m++;
m++;
return m;
}finally{
lock.unlock();
}
}
注意:return 要放到try块中,unlock方法要放到finally块中。如果在使用synchronized失败了,那么就会抛出一个异常,但是没有机会做任何清理工作。lock就可以做到。
(3)
tryLock
public boolean tryLock()
Acquires the lock only if it is not held by another thread at the time of invocation.
Acquires the lock if it is not held by another thread and returns immediately with the value true, setting the lock hold count to one. Even when this lock has been set to use a fair ordering policy, a call to tryLock() will immediately acquire the lock if it is available, whether or not other threads are currently waiting for the lock. This "barging" behavior can be useful in certain circumstances, even though it breaks fairness. If you want to honor the fairness setting for this lock, then use tryLock(0, TimeUnit.SECONDS) which is almost equivalent (it also detects interruption).
If the current thread already holds this lock then the hold count is incremented by one and the method returns true.
If the lock is held by another thread then this method will return immediately with the value false.
Specified by:
tryLock in interface Lock
Returns:
true if the lock was free and was acquired by the current thread, or the lock was already held by the current thread; and false otherwise.
这个方法是抢先获得锁。有个缺点,如果其他线程已经获得锁,那么它放回false后,继续执行下面的代码,达不到同步的作用,还是用lock吧
(4)
tryLock
public boolean tryLock(long timeout,
TimeUnit unit)
throws InterruptedException
Acquires the lock if it is not held by another thread within the given waiting time and the current thread has not been interrupted.
Acquires the lock if it is not held by another thread and returns immediately with the value true, setting the lock hold count to one. If this lock has been set to use a fair ordering policy then an available lock will not be acquired if any other threads are waiting for the lock. This is in contrast to the tryLock() method. If you want a timed tryLock that does permit barging on a fair lock then combine the timed and un-timed forms together:
if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
该方法的意思是在给定的时间内,去公平竞争锁。如果时间到还没有获得锁,则返回false。和synchronized不同,如果访问对象的某个synchronized方法,其它线程就不能访问该对象的所有synchronized方法。但是,如果没有synchronized而是在方法内部用了lock,就不会出现这种现象,其它线程还可以访问该对象的其它内部还有lock的方法。例如:
public class AttemptLocking {
private ReentrantLock lock = new ReentrantLock();
public void untimed() throws Exception {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock(): ");
Thread.sleep(5 * 1000);
System.out.println("时间已过");
} finally {
if (captured)
lock.unlock();
}
}
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(6, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(10, TimeUnit.SECONDS): " + captured);
} finally {
if (captured) {
lock.unlock();
} else {
System.out.println("没有执行");
}
}
}
public void f() {
System.out.println("其他方法");
}
public static void main(String[] args) {
final AttemptLocking al = new AttemptLocking();
ExecutorService exec = Executors.newCachedThreadPool();
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
al.untimed();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
al.timed();
}
};
Runnable r3 = new Runnable() {
@Override
public void run() {
al.f();
}
};
exec.execute(r1);
exec.execute(r3);
exec.execute(r2);
exec.shutdown();
}
}
4.
java.util.concurrent
Interface Future<V>
public interface Future<V>
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation. The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.
Sample Usage (Note that the following classes are all made-up.)
interface ArchiveSearcher { String search(String target); }
class App {
ExecutorService executor = ...
ArchiveSearcher searcher = ...
void showSearch(final String target) throws InterruptedException {
Future<String> future = executor.submit(new Callable<String>() {
public String call() { return searcher.search(target); }
});
displayOtherThings(); // do other things while searching
try {
displayText(future.get()); // use future
} catch (ExecutionException ex) { cleanup(); return; }
}
}
相关方法:
(1)cancel
boolean cancel(boolean mayInterruptIfRunning)
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
Parameters:
mayInterruptIfRunning - true if the thread executing this task should be interrupted; otherwise, in-progress tasks are allowed to complete
Returns:
false if the task could not be cancelled, typically because it has already completed normally; true otherwise
5.如果希望完成任务时,能够返回一个值,那么可以实现Callable接口而不是Runnable接口。例如:
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id) {
this.id = id;
}
public String call() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "result of TaskWithResult " + id;
}
}
public class CallableDemo {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
ArrayList<Future<String>> results = new ArrayList<Future<String>>();
for (int i = 0; i < 10; i++)
results.add(exec.submit(new TaskWithResult(i)));
for(int i=0;i<10;i++){
System.out.println("hahah"+i);
}
for (Future<String> fs : results)
try {
// get() blocks until completion:
System.out.println(fs.get());
} catch (InterruptedException e) {
System.out.println(e);
return;
} catch (ExecutionException e) {
System.out.println(e);
} finally {
exec.shutdown();
}
}
}