1.实现线程的基本方法
1.1定义任务
线程可以驱动任务,因此你需要一种描述任务的方式,这可以由Runnable接口来提供,实现Runnable接口并编写run()方法。
public class LiftOff implements Runnable{
public void run(){
System.out.print("haha");
Thread.yield();
}
}//创建一个任务类
//使用
LiftOff launch = new LiftOff();
launch.run();
run()一般要写作一个无限循环的形式,就意味着,除非有个条件,使run()结束,在run()中对静态方法 Thread.yield()的调用是对线程调度器的一种建议,他在声明:“我一完成生命周期最重要的一部分,此刻可以切换给其他线程”(降低当前线程的优先级,主动让出CPU)
1.2Thread类
将Runnable对象直接提交给一个Thread构造器;
public class LiftOff implements Runnable{
public void run(){
System.out.print("haha");
Thread.yield();
}
}//创建一个任务类
//使用
Thread t = new Thread(new LiftOff());
t.start();
Thread构造器只需要一个Runnable对象,调用start()方法时会自动调用Runnable中run方法,但是 start()方法会很快返回。
1.3 Executor
Executor帮助管理Thread对象,他在客户端和任务执行之间提供了一个间接层,Executor替代了在MoreBasicThreads中显示的创建Thread对象,ExecutorService(Executor的子类,具有服务生命周期的Executor)知道如何构建上下文来执行Runnable对象。
Executors中常见的线程池:
newCachedThreadPool:将为每一个任务都创建一个线程
newFixedThreadPool(int ):限制线程创建的数量
newSingleThreadExecutor():就是newFixedThreadPool(1),对于长期存活的任务来说非常有用。
public class CachedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
public class FixedThreadPool {
public static void main(String[] args) {
ExecutorService exec = Executors.newFixedThreadPool(5);
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
public class SingleThreadExecutor {
public static void main(String[] args) {
ExecutorService exec = Executors.newSingleThreadExecutor();
for(int i = 0; i < 5; i++)
exec.execute(new LiftOff());
exec.shutdown();
}
}
1.4 Callable接口
Runnable接口不返回任何值,如果希望在完成任务时能够返回一个值,可以实现Callable接口,Callable是一种具有类型参数的泛型,他的类型参数是从方法call()中返回的值,并且用ExecutorService.submit()来调用他。
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class TaskWithResult implements Callable<String> {
private int id;
public TaskWithResult(int id){
this.id = id;
}
public String call() throws Exception {
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++){
Future<String> fs = exec.submit(new TaskWithResult(i));
results.add(fs);
}
for (Future<String> fs : results) {
try {
System.out.println(fs.get());
} catch (Exception e) {
e.printStackTrace();
} finally{
exec.shutdown();
}
}
}
}
submit()方法会产生Future对象,它用Callable返回结果的特定类型进行了参数化。我们可以通过isDone()方法查看Future是否已经完成。当任务完成时我们可以通过调用get()方法来获取该结果。不过不用isDone()方法检查,get()方法将会阻塞直到获取到callable执行获取到结果。
1.5 休眠
sleep()的调用可以抛出InterruptedException异常,休眠 即阻塞。