1.Executor:Executor(执行器)将为你管理Thread对象,Executor在客户端和任务执行之间提供了一个间接层。ExecutorService(具有服务生命周期的Executor,例如关闭)知道如何构建恰当的上下文来执行Runnable对象。
使用如下:
public class Test1 implements Runnable {
private static int count = 0;
private final int id = count++;
public Test1() {
System.out.println();
}
@Override
public void run() {
System.out.println(id + " run() method is run");
Thread.yield();
}
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
// ExecutorService exec = Executors.newFixedThreadPool(3);
// ExecutorService exec = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
exec.execute(new Test1());
}
exec.shutdown();
}
}
/*Output:
0 run() method is run
1 run() method is run
2 run() method is run
3 run() method is run
4 run() method is run
*/
对shutdown()方法的调用可以防止新的任务被提交给这个Executor,其中:
*CachedThreadPool 将为每个任务都创建一个线程, 它是合理的Executor的首选。
*FixedThreadPool将一次性预先执行代价较高昂的线程分配,因而可以显示线程数量,这可以节省时间,你不用为每个任务都固定地付出创建线程的开销,在线程池中,现有线程在可能的情况下都会被自动复用。
*SingleThreadExecutor是线程数量为1的FixedThreadPool,如果向SingleThreadExecutor提交了多个任务,这些任务将排队。
2.*优先级:
调度器更倾向于让让优先级高的线程先执行。但是并不是说优先级高的线程执行时优先级低的线程得不到执行,也就是说,优先级不会导致死锁,优先级低的线程仅仅是执行的频率较低。在绝大多时间里,所有线程都应该以默认的优先级运行,试图操作线程的优先级通常是一种错误。
可以使用getPriority()方法获得线程的优先级,使用setPriority(n)方法来设定线程优先级。
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
System.out.println("hello thread! "+Thread.currentThread().getPriority());
}
以上Thread.currentThread()可以获得对驱动该任务的Thread对象的引用,设置线程的优先级一般在run()的开头不封设定,在构造器中设定它们不会有任何好处,因为Executor在此刻还没有开始执行任务
3.让步
当任务已经完成的差不多了觉得可以让其他线程工作了的时候可以给线程调度机制一个暗示:你的工作已经做得差不多了,可以让其他线程使用cpu了,这个暗示将通过调用yield()方法(不过这只是一个暗示,没有任何机制保证它将被采纳)。当调用yield()时你也是建议具有相同优先级的其他线程可以运行。
4.后台线程
所谓后台线程,是指在程序运行时在后台提供一种通用服务的线程,并且这种线程不属于程序中不可或缺的一部份。在线程启动之前调用setDaemon()方法可以将线程设置为后台线程,当所有非后台线程结束时,程序也就终止了,同时会杀死进程中的所有后台线程,后台线程在不执行finally子句的时候就会终止其run()方法。
for(int i = 0; i<10; i++) {
Thread daemon = new Thread(new Test1);
daemon.setDaemin(true);
daemon.start();
}