(1)如何创建并运行一个线程?
有三种方法
- 继承 java.lang.Thread 类,重写 run() 方法
public class TestThread extends Thread {
@Override
public void run() {
//do something
}
}
调用这个类的 start() 方法就能开始运行线程,当然这里不一定立刻会运行,只是进入就绪状态,注意每个线程只能调用一次 start() 方法。
public static void main(String[] args) {
Thread testThread = new TestThread();
testThread.start();
}
- 实现 Runnable 接口
public class TestThread implements Runnable {
public void run() {
//do something
}
}
将该类传入 Thread 的构造方法作为 target
public static void main(String[] args) {
Thread testThread = new Thread(new TestThread());
testThread.start();
}
(2)如何创建和使用Java自带的线程池?
- 使用 java.util.concurrent.ThreadPoolExecutor 类,这个类有多个构造方法,且参数较多,详情可查阅 API 文档。通常情况下使用 Executors 类来创建线程池。
public class App {
public static void main(String[] args) {
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20, 10000, TimeUnit.MICROSECONDS, new ArrayBlockingQueue(10));
threadPool.execute(new MyThread());
}
}
class MyThread implements Runnable {
@Override
public void run() {
//do something
}
}
- 使用 Executors 类的静态方法创建线程池
Executors.newCachedThreadPool(); //创建缓冲线程池
Executors.newFixedThreadPool(nThreads); //创建固定大小线程池
Executors.newScheduledThreadPool(corePoolSize); //创建计划线程池
Executors.newSingleThreadExecutor(); //创建单线程池
还有其他线程池的创建方法这里就不在叙述了。查看这些方法的源码可以发现其实是返回一个新建的 ThreadPoolExecutor 类,相当于帮你配置好构造参数。
向线程池提交任务
execute(Runnable command),还有一个 submit(Runnable task) 方法也可以提交任务,其实内部还是调用的 execute,区别是 submit 方法返回一个 Future。线程池包含的知识点十分多,这里有很详细的讲解
(3)如何定时运行一个任务?
public class App {
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
scheduledThreadPool.scheduleWithFixedDelay(new MyThread(), 10, 3, TimeUnit.SECONDS); //执行线程 new MyThread(), 在 10 秒之后, 以 3 秒钟为频率执行
}
}
class MyThread implements Runnable {
public void run() {
//do something
}
}
首先我们先使用 Executors 创建一个 ScheduledThreadPoolExecutor 类,从名字可以看出它可以计划地执行线程。它有两个周期性运行线程地方法
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
这两个方法的区别是,如果这个线程的执行时间大于 delay/peroid 这个时间,那么当线程执行完成后,前者会等到过了 delay 时间之后再执行线程,而后者会直接执行线程。