文章目录
- 继承Thread
- 实现Runnable接口
- 实现Callable接口
- new Thread方式的缺点
- 通过线程池创建
- newSingleThreadExecutor
- newFixedThreadPool
- newScheduledThreadPool
- newCachedThreadPool
- 线程池的作用
继承Thread
public class ThreadTest {
public static void main(String[] args) {
Thread thread1 = new MyThread();
Thread thread2 = new MyThread();
Thread thread3 = new MyThread();
thread1.start();
thread2.start();
thread3.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println(this.getName() + " is running。。。");
}
}
## 匿名内部类创建线程
new Thread(){
@Override
public void run() {
System.out.println("通过匿名内部类创建的线程 is running ...");
}
}.start();
实现Runnable接口
public class RunnableTest {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyRunnableThread());
Thread thread2 = new Thread(new MyRunnableThread());
Thread thread3 = new Thread(new MyRunnableThread());
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnableThread implements Runnable{
@Override
public void run() {
System.out.println(" Runnable thread is running。。。");
}
}
实现Callable接口
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallableThread myCallableThread = new MyCallableThread();
FutureTask<String> ft = new FutureTask<>(myCallableThread);
Thread thread = new Thread(ft);
thread.start();
System.out.println(ft.get());
}
}
class MyCallableThread implements Callable<String>{
@Override
public String call() throws Exception {
return "Callable 线程创建了";
}
}
new Thread方式的缺点
- 每次创建线程都要新建对象,性能较差;
- 线程缺乏统一的管理,线程的可维护性差;
- 线程不可重用,创建销毁开销较大。
通过线程池创建
newSingleThreadExecutor
创建一个只有一个线程的线程池。
ExecutorService singleExecutorService = Executors.newSingleThreadExecutor();
for(int i=0;i<10;i++){
int index = i;
singleExecutorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("由newSingleThreadExecutor线程池创建了一个线程");
System.out.println(Thread.currentThread().getName() + ":" + index);
}
});
}
可以看到控制台打印结果中只有一种线程工作,结果依次输出,该线程按指定的顺序执行任务。
newFixedThreadPool
创建一个指定大小的线程池(指定的线程个数,即线程最大的并发数)。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for(int i=0;i<10;i++){
int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("由newFixedThreadPool线程池创建了一个线程");
System.out.println(Thread.currentThread().getName() + ":" + index);
}
});
}
从打印结果中可以看到,一共创建了指定的线程个数(此例为3个)并发的执行任务。
newScheduledThreadPool
创建一个指定大小的线程池,与newFixedThreadPool类似,但它支持定时及周期性任务的执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
for(int i=0;i<10;i++){
int index = i;
// Thread.sleep(1000);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("由newScheduledThreadPool线程池创建了一个线程");
System.out.println(Thread.currentThread().getName() + ":" + index);
}
},3, TimeUnit.SECONDS);
}
newCachedThreadPool
创建一个可缓存的线程池,它可以灵活的回收空闲线程或者创建新线程。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for(int i=0;i<5;i++){ //10
int index = i;
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println("由newCachedThreadPool线程池创建了一个线程");
System.out.println(Thread.currentThread().getName() + ":" + index);
}
});
}
当for循环中遍历的次数为10时,一共创建了10个线程执行任务;
当for循环中遍历的次数为5时,一共创建了5个线程执行任务。
可以看到,当当前并发的任务量不同时,它可以按需创建不同大小的线程池,已达到最佳性能。
线程池的作用
- 按照系统的环境情况,限制系统中执行线程的数量;
- 每个工作线程都可以被重复利用,可执行多个任务,从而减少创建和销毁线程的次数;
- 根据系统的承受能力,调整线程池中工作线程的个数,防止内存消耗过大