四、从任务中产生返回值
因为Runnable和Thread中的run()方法的声明是固定的,起返回值为void,即用这种方式执行任务时不能有返回值的。如果希望任务在执行完之后返回一个值,那么可以实现Callable接口。Callable接口具有泛型,该泛型指定从方法call中返回的值得类型。实现Callable接口的任务只能用ExecutorService.submit()执行他。
实现Callable接口类
public class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(){}
public TaskWithResult(int i){
this.id = i;
}
@Override
public String call() throws Exception {
System.out.println("the " + id + " Process");
return "Result of task:" + id;
}
}
获得任务执行的返回值,注意:ExecutorService.submit()的返回值是Future类型的。
public class CallableDemo {
public static void main(String[] args) {
ExecutorService exe = Executors.newCachedThreadPool();
ArrayList<Future<String>> result = new ArrayList<Future<String>>();
for(int i = 0; i < 5; i++){
result.add(exe.submit(new TaskWithResult(i)));
}
for(Future<String> ret : result){
try {
System.out.println(ret.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
因为任务是在子线程中执行的,而主线程不会等待子线程的完成,所以可以用isDone()判断Future是否已经完成,如果已经完成,则可以用get()获取返回值,当然也可以直接get()获取返回值,因为get()方法时阻塞的。
五、休眠
使线程休眠一段时间之后再开始执行任务。
public class SleepingTask extends LiftOff {
public void run(){
try{
while(countDown-- > 0){
System.out.println(status());
//Thread.sleep(100);
TimeUnit.MILLISECONDS.sleep(100);
}
}catch (InterruptedException e) {
System.err.println("Interrupted");
}
}
public static void main(String[] args) {
ExecutorService exe = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++){
exe.submit(new SleepingTask());
}
exe.shutdown();
}
}
六、优先级
线程的优先级代表线程的重要性,线程调度器倾向于优先级高的线程优先执行,但这并不是安全权的,即优先级高的线程并不是一定先执行。更多的体现在任务的执行频率,即占用CPU的时间。
可以用setPriority()和getPriority()来设置和获取线程的优先级。
JDK有10个优先级,但他与操作系统映射的不是很好,如果要跨平台使用优先级,应该只使用MAX_PRIORITY,MORM_PRIORITY,MIN_PRIORITY三种优先级。
7、让步
yield()方法,通知调度器,此线程的主要工作已完成,可以让其他线程占用CPU了。但无法保证此线程会退出CPU,而由其他线程占用CPU。