您的位置:首页 > 编程语言 > Java开发

[Java并发]-03-线程执行器的使用

2014-11-15 08:07 393 查看

3 线程执行器

3.1 Executors工厂

newCachedThreadPool创建ExecutorService 无界线程池,可以进行自动线程回收

public static ExecutorService newCachedThreadPool()
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory)


newFixedThreadPool创建ExecutorService 固定大小线程池

public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory)


newSingleThreadExecutor创建ExecutorService单个后台线程
public static ExecutorService newSingleThreadExecutor()
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory)


newScheduledThreadPool创建ScheduledExecutorService
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)


newSingleThreadScheduledExecutor 创建ScheduledExecutorService
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)


ThreadFactory 是提供线程的工厂,执行器 根据工厂创建其中的线程

方法命名上single的不能成为pool 就是称为executor



3.2 ThreadPoolExecutor的构造方法

3.3 使用ThreadPoolExecutor

public static void main(String[] args) {
System.out.println("=========main start");
final ThreadPoolExecutor exec = (ThreadPoolExecutor) Executors
.newCachedThreadPool(new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.execute(new Runnable() {

@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("AAA--" + i);
}
}
});

exec.execute(new Runnable() {

@Override
public void run() {

for (int i = 0; i < 200; i++) {
System.out.println("BBB--" + i);
}
}
});

exec.execute(new Runnable() {

@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("CCC--" + i);
}

}
});

try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ConcurrencyUtils.printThreadPoolExecutorInfo(exec);

System.out.println("=========main end");
}

shutdown()和shutdownNow();都不能终止已经执行的任务,再增加新的任务会向执行器所在线程抛出RejectedExecutionException异常,如未处理该处理异常,执行器所在线程将终止,但是执行器中的任务还将继续执行。

shutdownNow会将排队的任务舍弃,shutdown则会将队列中的任务执行完毕。

public static class Task implements Runnable {
private String id;

Task(int id) {
this.id= "Task-" + id;
}

@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(id + "   "+ i);
}
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ThreadPoolExecutor exec = (ThreadPoolExecutor) Executors
.newFixedThreadPool(5, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

for (int i = 0; i < 10; i++) {
exec.execute(new Task(i));
}

exec.shutdownNow();
System.out.println(">>>>>>>>>>>>>>>shutdownNow");

try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
ConcurrencyUtils.printThreadPoolExecutorInfo(exec);

System.out.println("=========main end");
}


...
exec.getPoolSize()=0

exec.getCorePoolSize()=5

exec.getLargestPoolSize()=5

exec.getMaximumPoolSize()=5

exec.getActiveCount()=0

exec.getTaskCount()=5

exec.getCompletedTaskCount()=5

=========main end

如果改成shutdow()

...

exec.getPoolSize()=0

exec.getCorePoolSize()=5

exec.getLargestPoolSize()=5

exec.getMaximumPoolSize()=5

exec.getActiveCount()=0
exec.getTaskCount()=10

exec.getCompletedTaskCount()=10

=========main end

newSingleThreadExecutor只有一个线程的newFixedThreadPool,所有task都在一个线程中执行,也不难看出task是顺序执行的,一个task完成了 才进行下个task。

这个例子可以换成newFixedThreadPool和newCachedThreadPool等,看看线程池中线程分配情况。

public static class Task implements Runnable {
private String id;

Task(int id) {
this.id= "Task-" + id;
}

@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(id + "   " + i  + "   " + Thread.currentThread().getName() );
}
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors
.newSingleThreadExecutor(new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

for (int i = 0; i < 10; i++) {
exec.execute(new Task(i));
}

try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("=========main end");
}


3.4下面看看执行器框架的优势之一-----运行并返回结果

Future<?> submit(Runnable task);

<T> Future<T> submit(Runnable task, T result);

<T> Future<T> submit(Callable<T> task);


Callable接口,call方法中实现任务具体的逻辑,和Runnable的run方法类似,不过Callable是个泛型接口,泛型是返回值的类型。

Future接口 获取Callable返回的结果,并管理他们的状态

继续demo

public static class Task implements Runnable {
private String id;

Task(int id) {
this.id = "Task-" + id;
}

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(id + "   " + i + "   "
+ Thread.currentThread().getName());
}
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors.newFixedThreadPool(4,
new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

Callable<Task> callable = new Callable<Task>() {

@Override
public Task call() throws Exception {
System.out.println("call " + "   "
+ Thread.currentThread().getName());

try {
                                        TimeUnit.NANOSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Task("call中的task");
}

};
Future<Task> future = exec.submit(callable);

do {
System.out.println("=========future.isDone()  " + future.isDone());
} while (!future.isDone());

Task command = null;
if (future.isDone()) {
try {
command = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
exec.execute(command);
exec.execute(command);
exec.execute(command);
exec.execute(command);
System.out.println("=========main end");
}


future.isDone()来判断task(Callable的对象)是否执行完成,

其实不需要判断

future.get方法是阻塞的将一直等待call方法执行完成,如果在get方法等待过程中线程中断了则抛出 InterruptedException,如果call方法中抛出了异常则 get方法随之抛出ExecutionException异常

改动一下代码如下

	public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService
4000
exec = Executors.newFixedThreadPool(4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

Callable<Task> callable = new Callable<Task>() {

@Override
public Task call() throws Exception {
System.out.println("call " + " " + Thread.currentThread().getName());

try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Task("call中的task");
}

};
Future<Task> future = exec.submit(callable); // 调用submit返回一个结果,结果是Callable中call()方法返回的
// 是一个Runnble对象

Task command = null;
try {
System.out.println("=========future.get s");
command = future.get();
System.out.println("=========future.get e");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

// 通过future.get()获得返回的结果对象,这个对象是个runnable对象可以 再用执行器执行
exec.execute(command);
exec.execute(command);
exec.execute(command);
exec.execute(command);
System.out.println("=========main end");
}

还可以再改改
用    V get(long timeout, TimeUnit unit) 方法

如果call超过timeout时间还没有完成则抛出TimeoutException,可以用来限制等待时间,不是一直等待下去。

下面代码中 如果超时 command是null;

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors.newFixedThreadPool(4,
new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

Callable<Task> callable = new Callable<Task>() {

@Override
public Task call() throws Exception {
System.out.println("call " + "   "
+ Thread.currentThread().getName());

try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Task("call中的task");
}

};
Future<Task> future = exec.submit(callable);

Task command = null;
try {
System.out.println("=========future.get s");
command = future.get(2, TimeUnit.SECONDS);
System.out.println("=========future.get e");
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (command != null) {
exec.execute(command);
exec.execute(command);
exec.execute(command);
exec.execute(command);
}
System.out.println("=========main end");
}


3.5 运行多个任务处理第一个结果

下面看看ExecutorService invokeAny 和invokeAll两个方法

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;

<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;


有这样一个问题:线程竞赛只用最快的结果

public static class Task implements Callable<String> {
private String id;
private int workTime;

Task(String id, int workTime) {
this.id = "Task-" + id;
this.workTime = workTime;
}

@Override
public String call() throws Exception {
try {
TimeUnit.SECONDS.sleep(workTime);
} catch (InterruptedException e) {
System.out.println(id + "   " + "InterruptedException");
}
System.out.println(id + "   " + Thread.currentThread().getName());

return id;
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors.newFixedThreadPool(4,
new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
List<Task> tasks = new ArrayList<Task>();
tasks.add(new Task("2sTask", 2));
tasks.add(new Task("3sTask1", 3));
tasks.add(new Task("3sTask2", 3));
tasks.add(new Task("3sTask3", 3));
tasks.add(new Task("1sTask1", 1));
tasks.add(new Task("1sTask2", 1));
tasks.add(new Task("1sTask3", 1));
tasks.add(new Task("10sTask", 10));
String result = null;
try {
result = exec.invokeAny(tasks);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

System.out.println("result  = " + result);
System.out.println("=========main end");
}


=========main start

Task-2sTask   Thread-0

result  = Task-2sTask

=========main end

Task-3sTask3   InterruptedException

Task-3sTask3   Thread-3

Task-3sTask2   InterruptedException

Task-3sTask2   Thread-2

Task-1sTask1   InterruptedException

Task-1sTask1   Thread-0

Task-3sTask1   InterruptedException

Task-3sTask1   Thread-1

通过结果可以看出当最快的结果返回后,执行器中断了其它所有线程,没有执行的task也从队列里清除了。

3.6 运行多个任务处理所有结果

    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)

        throws InterruptedException;


返回的List<Future<T>>是用来获得任务的结果,因为invokeAll是阻塞的,返回时候所有的任务都已经完成了。

也就是所有的Future对象isDone()都会返回true;通过下面的例子也可以说明这点

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors.newFixedThreadPool(4,
new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
List<Task> tasks = new ArrayList<Task>();
tasks.add(new Task("2sTask", 2));
tasks.add(new Task("3sTask1", 3));
tasks.add(new Task("3sTask2", 3));
tasks.add(new Task("3sTask3", 3));
tasks.add(new Task("1sTask1", 1));
tasks.add(new Task("1sTask2", 1));
tasks.add(new Task("1sTask3", 1));
tasks.add(new Task("10sTask", 10));
 
List<Future<String>> results = null;

try {
results = exec.invokeAll(tasks);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (Future<String> result : results) {
try {
System.out.println("result  = " + result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("=========main end");
}


=========main start

Task-2sTask   Thread-0

Task-1sTask1   Thread-0

Task-3sTask2   Thread-2

Task-3sTask3   Thread-3

Task-3sTask1   Thread-1

Task-1sTask2   Thread-0

Task-1sTask3   Thread-2

Task-10sTask   Thread-3

result  = Task-2sTask

result  = Task-3sTask1

result  = Task-3sTask2

result  = Task-3sTask3

result  = Task-1sTask1

result  = Task-1sTask2

result  = Task-1sTask3

result  = Task-10sTask
=========main end

3.7 [b]ExecutorService和ScheduledExecutorService[/b]

public interface ScheduledFuture<V> extends Delayed, Future<V> {
}
 
ExecutorService中的时间都是timeout,是任务的时限,一般如果在时限内没有完成则中断任务并且清空队列中的任务

boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;

ScheduledExecutorService的schedule中的参数是delay,delay是延迟执行

public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);

public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);


这里要注意scheduleWithFixedDelay和scheduleAtFixedRate没有callable的参数,只能运行Runnable对象,schedule可以传入Runnable和Callable

3.8 延时执行任务

public static class Task implements Callable<String> {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public String call() throws Exception {
System.out.println(id + "   " + Thread.currentThread().getName());
return id;
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
1, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.schedule(new Task("[schedule task]"), 5, TimeUnit.SECONDS);
try {
exec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========main end");
}

=========main start

Task-[schedule task]   Thread-0

=========main end

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
1, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.schedule(new Task("[schedule task]"), 5, TimeUnit.SECONDS);
try {
exec.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========main end");
}


=========main start

=========main end

Task-[schedule task]   Thread-0

再改改增加一个task并且延迟时间比第一个task短。

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.schedule(new Task("[schedule task1]"), 3, TimeUnit.SECONDS);
exec.schedule(new Task("[schedule task2]"), 1, TimeUnit.SECONDS);
try {
exec.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========main end");
}


=========main start

Task-[schedule task2]   Thread-0

Task-[schedule task1]   Thread-1

=========main end

看看shutdown和shutdownNow能否阻止schedule的task

通过实验shutdown不能阻止schedule的task,仍然按延迟时间执行了,awaitTermination设置失效,不再等待

仍然输出

=========main start

Task-[schedule task2]   Thread-0

Task-[schedule task1]   Thread-1

=========main end

而exec.shutdownNow();调用后不仅schedule的task都没有执行,awaitTermination也没有作用了 直接输出end了

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.schedule(new Task("[schedule task1]"), 3, TimeUnit.SECONDS);
exec.schedule(new Task("[schedule task2]"), 1, TimeUnit.SECONDS);
//		exec.shutdown();  // 这里shutdown不能阻止schedule的task,仍然按延迟时间执行了,awaitTermination设置失效,不再等待10s
exec.shutdownNow();  // 这里shutdownNow阻止延迟的task执行,同时awaitTermination设置失效,不再等待
try {
exec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========main end");
}


=========main start

=========main end

3.9 setExecuteExistingDelayedTasksAfterShutdownPolicy

下面看看这个方法  ((ScheduledThreadPoolExecutor)exec).setExecuteExistingDelayedTasksAfterShutdownPolicy(false);

改变了策略shutdown,传入false时再调用shutdown会产生和shutdownNow一样的效果(不仅schedule的task都没有执行,awaitTermination也没有作用了 直接输出end了)

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
exec.schedule(new Task("[schedule task1]"), 3, TimeUnit.SECONDS);
exec.schedule(new Task("[schedule task2]"), 1, TimeUnit.SECONDS);
/**
* 改变了策略shutdown,传入false时再调用shutdown会产生和shutdownNow一样的效果(不仅schedule的task都没有执行,awaitTermination也没有作用了 直接输出end了)
*/
((ScheduledThreadPoolExecutor)exec).setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
exec.shutdown();  // 由于上面一句改变了shutdow的策略,这里shutdown和shutdownNow效果一样,awaitTermination设置失效,不再等待10s

try {
exec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("=========main end");
}


=========main start

=========main end

3.10 周期执行任务

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);

public
d6f0
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);


3.10.1 scheduleAtFixedRate

这个方法比较有意思,没有以Callback作为参数,所以其返回值飞泛型是“?”

scheduleAtFixedRate第一个参数是task 不是Callback所以不能返回值,ScheduledFuture应该是用来看执行状态的

initialDelay这个参数是第一task的延时 单位是第四个参数的

period是之后发出任务的间隔

ScheduledFuture继承自Future<V>

public interface ScheduledFuture<V> extends Delayed, Future<V> {
}

现在写个demo来试试这个方法

public class Task implements Runnable {
private String id;
private long creatTime;

Task(String id) {
this.id = "Task-" + id;
creatTime = System.currentTimeMillis();
}

@Override
public void run() {
System.out.println("开始执行  时间:" + ((System.currentTimeMillis() - creatTime) / 1000) + " " + id + "   "
+ Thread.currentThread().getName());
try {
// Thread.sleep(2000);// 2s 没有超过了设定的delay时间 会按设定的delay时间进行下一个task
Thread.sleep(6000); // 6s 超过了设定的delay时间,会等待task结束再进行下一个task
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("执行结束 " + id + "   " + Thread.currentThread().getName());
}
}
public class Main {

/**
* @param args
*/
public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
// 延迟1s,然后每隔5s执行一次
// 发现即便线程池中可以有4个线程来处理任务但是任务仍然是处理完了才回发出下一个task,如果task时间超过了设定的delay时间,会等待task结束再进行下一个task
ScheduledFuture<?> sf = exec.scheduleAtFixedRate(new Task("[schedule task]"), 1, 5, TimeUnit.SECONDS);

System.out.println("=========main end");
}
}


上面的如所预料的不断输出。

改一改,

发现即便线程池中可以有4个线程来处理任务但是任务仍然是处理完了才回发出下一个task,如果task时间超过了设定的delay时间,会等待task结束再进行下一个task

log上添加时间看得更清楚;如果task的时间超过的了周期,也要等到task执行完毕后立即发送下个task

看看两种时间情况

public static class Task implements Runnable { //不能再是Callable
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
System.out.println(new Date() +":"+ id + "  task start  " + Thread.currentThread().getName());
try {
<strong>TimeUnit.SECONDS.sleep(1);</strong>
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date() +":"+ id + "  task end  " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
ScheduledFuture<?> sf = exec.scheduleAtFixedRate(new Task("[schedule task1]"), 1, 5, TimeUnit.SECONDS);

System.out.println("=========main end");
}


=========main start

=========main end
Sat Nov 15 14:38:58 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:38:59 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:03 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:39:04 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:08 CST 2014:Task-[schedule task1]  task start  Thread-1

Sat Nov 15 14:39:09 CST 2014:Task-[schedule task1]  task end  Thread-1
Sat Nov 15 14:39:13 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:39:14 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:18 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:39:19 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:23 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:39:24 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:28 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:39:29 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:33 CST 2014:Task-[schedule task1]  task start  Thread-0
Sat Nov 15 14:39:34 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:39:38 CST 2014:Task-[schedule task1]  task start  Thread-0
Sat Nov 15 14:39:39 CST 2014:Task-[schedule task1]  task end  Thread-0

倘若task执行的时间大于delay的时间,会在执行完task立即发出下一个task,而不是在没执行完上个task的时候 又发出一个task,虽然此时有空闲线程

public static class Task implements Runnable {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
System.out.println(new Date() +":"+ id + "  task start  " + Thread.currentThread().getName());
try {
<strong>TimeUnit.SECONDS.sleep(10);</strong>
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date() +":"+ id + "  task end  " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
ScheduledFuture<?> sf = exec.scheduleAtFixedRate(new Task("[schedule task1]"), 1, 5, TimeUnit.SECONDS);

System.out.println("=========main end");
}
=========main start

=========main end

Sat Nov 15 14:40:14 CST 2014:Task-[schedule task1]  task start  Thread-0
Sat Nov 15 14:40:24 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:40:24 CST 2014:Task-[schedule task1]  task start  Thread-0


Sat Nov 15 14:40:34 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:40:34 CST 2014:Task-[schedule task1]  task start  Thread-1

Sat Nov 15 14:40:44 CST 2014:Task-[schedule task1]  task end  Thread-1

Sat Nov 15 14:40:44 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:40:54 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:40:54 CST 2014:Task-[schedule task1]  task start  Thread-0

3.10.2 scheduleWithFixedDelay

public static class Task implements Runnable {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
System.out.println(new Date() +":"+ id + "  task start  " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date() +":"+ id + "  task end  " + Thread.currentThread().getName());
}
}
public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
ScheduledFuture<?> sf = exec.scheduleWithFixedDelay(new Task("[schedule task1]"), 1, 5, TimeUnit.SECONDS);

System.out.println("=========main end");
}


=========main start

=========main end

Sat Nov 15 14:42:24 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:42:25 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:42:30 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:42:31 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:42:36 CST 2014:Task-[schedule task1]  task start  Thread-1

Sat Nov 15 14:42:37 CST 2014:Task-[schedule task1]  task end  Thread-1

Sat Nov 15 14:42:42 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:42:43 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:42:48 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:42:49 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:42:54 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:42:55 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:43:00 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:43:01 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:43:06 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:43:07 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:43:12 CST 2014:Task-[schedule task1]  task start  Thread-0

可以看此时 是 任务结束后再延迟固定的时间

public static class Task implements Runnable {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
System.out.println(new Date() + ":" + id + "  task start  "
+ Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(new Date() + ":" + id + "  task end  "
+ Thread.currentThread().getName());
}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(
4, new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});
ScheduledFuture<?> sf = exec.scheduleWithFixedDelay(new Task(
"[schedule task1]"), 1, 5, TimeUnit.SECONDS);

System.out.println("=========main end");
}
=========main start

=========main end

Sat Nov 15 14:43:58 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:44:08 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:44:13 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:44:23 CST 2014:Task-[schedule task1]  task end  Thread-0

Sat Nov 15 14:44:28 CST 2014:Task-[schedule task1]  task start  Thread-1

Sat Nov 15 14:44:38 CST 2014:Task-[schedule task1]  task end  Thread-1

Sat Nov 15 14:44:43 CST 2014:Task-[schedule task1]  task start  Thread-0

Sat Nov 15 14:44:53 CST 2014:Task-[schedule task1]  task end  Thread-0
Sat Nov 15 14:44:58 CST 2014:Task-[schedule task1]  task start  Thread-0

3.11  取消在执行的任务

Future#cancel(true);是可以发出中断信号,但是线程仍然在一直运行。

如果任务还没有开始处理,cancel则会让任务不再被处理。

如果任务已经开始则会发出中断信号 任务会继续运行。、

(???如何理解中断信号,一个线程中如果有sleep产生中断信号后使之抛出中断异常,但如果线程中是一个死循环,中断信号并不能使之停止循环???)(???中断异常抛出的原理???)

public static class Task implements Runnable {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public void run() {
System.out.println(new Date() + ":" + id + "  task start  "
+ Thread.currentThread().getName());

while(true) {
System.out.println(new Date() + ":" + id + "  task running  "
+ Thread.currentThread().getName());

}

}
}

public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors.newSingleThreadExecutor(
new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

Future<?> f = exec.submit(new Task("task"));
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
f.cancel(true);
System.out.println("=========main end");
}


3.12 FutureTask

public static class Task implements Callable<String> {
private String id;

Task(String id) {
this.id = "Task-" + id;
}

@Override
public String call() throws Exception {

System.out.println(id + "   " + Thread.currentThread().getName());

return id;
}
}
public static void main(String[] args) {
System.out.println("=========main start");
final ExecutorService exec = Executors
.newSingleThreadExecutor(new ThreadFactory() {

@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
});

FutureTask<String> ftask = new FutureTask<String>(new Task("task")){

@Override
protected void done() {
System.out.println("=========FutureTask done");
super.done();
}

};
exec.submit(ftask);

System.out.println("=========main end");
}
=========main start

=========main end

Task-task   Thread-0

=========FutureTask done
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: