创建多线程的方式四:使用线程池(这也是真正开发常选择的方式)
线程池的好处:
提高了程序执行效率(因为线程已经提前创建好了)
提高了资源的复用率(因为执行完的线程并未销毁,二是可以继续执行其他的任务)
可以设置相关的参数,对线程池中的线程使用进行资源管理
ThreadPool + Runnable
格式归纳:
class A implements Runnable{@override run({XXX})}
class B implements Runnable{@override run({XXX})}
public class ThreadPool{
public static void main(String[] args) {
ExecutorService x = Executors.newFixedThreadPool(N);//提供N个线程池
//ExecutorService是一个接口,它表示一个执行器,用于管理和控制异步任务的执行。
//x 是一个变量,用于存储对 ExecutorService 对象的引用。
//Executors是一个工具类,提供了一系列静态工厂方法,用于创建不同类型的线程池。
//newFixedThreadPool(N) 是 Executors 类中的一个静态方法,它用于创建一个固定大小为N的线程池。
//当这句代码执行后,x 变量就会持有一个指向新创建的固定大小线程池的引用。通过这个引用,你可以向线程池提交任务(Runnable 或 Callable 对象),控制线程池的关闭等。
x.execute(new A());
x.execute(new B());
x.shutdown(); //用完了及时关闭,养成良好的习惯
}
线程池程序举例(两个线程,一个输出奇数。一个输出偶数)-使用Runnable接口完成:
package ThreadPool;
import java.lang.reflect.Executable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
//创建并使用多线程的第四种方法:使用线程池
//第一个线程打印偶数
class NumberThread implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i%2 == 0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
//第二个线程 打印奇数
class NumberThread1 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i%2 != 0){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//提供指定线程数量的线程池
ExecutorService x = Executors.newFixedThreadPool(10);
//下面是一个强制类型转换
//这行代码尝试将x(一个ExecutorService对象)强制转换为ThreadPoolExecutor类型,并将其赋值给变量y。
// 这通常是不安全的,因为ExecutorService是一个接口,可以有多种实现,而ThreadPoolExecutor只是其中之一。
// 虽然在这个特定的例子中,通过Executors.newFixedThreadPool创建的ExecutorService对象实际上是一个ThreadPoolExecutor实例,
// 但这种强制类型转换仍然是不推荐的,因为它降低了代码的健壮性。
// 如果将来x由不同的ExecutorService实现提供,这行代码将会抛出ClassCastException。
// 此处创建y是为了配合下一行的调整线程池大小
//ThreadPoolExecutor y =(ThreadPoolExecutor) x;
//可以后续手动调整线程池的属性
//System.out.println(x.getClass()); //ThreadPoolExecutor
//y.setMaximumPoolSize(15);//可再次设置线程池中线程数的上限
//下面就是具体想让线程池执行哪些事情,调哪个class里的run,直接调就行
//执行指定线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象
x.execute(new NumberThread());//适用于Runnable
x.execute(new NumberThread1());//适用于Runnable
//x.submit(Callable callable); //(本例子中是Runnable方式),类似的,也可以使用Callable接口方式(上面对应的Thread调用模块那也需要改)
// 若需要使用Callable接口方式的返回值,用submit调用
//关闭池子
x.shutdown();
}
}
运行结果:
pool-1-thread-1:0
pool-1-thread-1:2
pool-1-thread-1:4
pool-1-thread-1:6
pool-1-thread-1:8
pool-1-thread-1:10
pool-1-thread-1:12
pool-1-thread-1:14
pool-1-thread-1:16
pool-1-thread-1:18
pool-1-thread-1:20
pool-1-thread-1:22
pool-1-thread-1:24
pool-1-thread-1:26
pool-1-thread-1:28
pool-1-thread-1:30
pool-1-thread-1:32
pool-1-thread-1:34
pool-1-thread-1:36
pool-1-thread-1:38
pool-1-thread-1:40
pool-1-thread-1:42
pool-1-thread-1:44
pool-1-thread-1:46
pool-1-thread-1:48
pool-1-thread-1:50
pool-1-thread-1:52
pool-1-thread-1:54
pool-1-thread-1:56
pool-1-thread-1:58
pool-1-thread-1:60
pool-1-thread-1:62
pool-1-thread-2:1
pool-1-thread-2:3
pool-1-thread-2:5
pool-1-thread-2:7
pool-1-thread-2:9
pool-1-thread-2:11
pool-1-thread-2:13
pool-1-thread-2:15
pool-1-thread-2:17
pool-1-thread-2:19
pool-1-thread-2:21
pool-1-thread-2:23
pool-1-thread-2:25
pool-1-thread-2:27
pool-1-thread-2:29
pool-1-thread-2:31
pool-1-thread-2:33
pool-1-thread-2:35
pool-1-thread-2:37
pool-1-thread-2:39
pool-1-thread-2:41
pool-1-thread-2:43
pool-1-thread-2:45
pool-1-thread-2:47
pool-1-thread-2:49
pool-1-thread-2:51
pool-1-thread-2:53
pool-1-thread-2:55
pool-1-thread-2:57
pool-1-thread-2:59
pool-1-thread-2:61
pool-1-thread-2:63
pool-1-thread-2:65
pool-1-thread-2:67
pool-1-thread-2:69
pool-1-thread-2:71
pool-1-thread-2:73
pool-1-thread-2:75
pool-1-thread-2:77
pool-1-thread-2:79
pool-1-thread-2:81
pool-1-thread-2:83
pool-1-thread-2:85
pool-1-thread-2:87
pool-1-thread-2:89
pool-1-thread-2:91
pool-1-thread-2:93
pool-1-thread-2:95
pool-1-thread-2:97
pool-1-thread-2:99
pool-1-thread-1:64
pool-1-thread-1:66
pool-1-thread-1:68
pool-1-thread-1:70
pool-1-thread-1:72
pool-1-thread-1:74
pool-1-thread-1:76
pool-1-thread-1:78
pool-1-thread-1:80
pool-1-thread-1:82
pool-1-thread-1:84
pool-1-thread-1:86
pool-1-thread-1:88
pool-1-thread-1:90
pool-1-thread-1:92
pool-1-thread-1:94
pool-1-thread-1:96
pool-1-thread-1:98
Process finished with exit code 0
ThreadPool + Callable
当然也可以使用implements Callable构建,call结构可以有返回值,调用时候稍有不同。
调用结构对应归纳为:
class A implements Callable{call(){XXX return result_a}}
public class 主程序 {
public static void main(String[] args) {
//提交N个线程池
ExecutorService x = Executors.newFixedThreadPool(N);
Future f_obj= x.submit(new A()); //创建Callable任务并且提交到线程池
f_obj.get(); //获取call结构的return值result_a
//System.out.println(f_obj.get());//也可以打印输出这个值
x.shundown();//用完了及时关闭
}
}
具体代码如下:
package ThreadPool;
import java.util.concurrent.*;
public class OddEvenNum {
public static void main(String[] args) {
ExecutorService x = Executors.newFixedThreadPool(4);
//创建Callable任务并且提交到线程池
Future f_e= x.submit(new Even());
Future f_o= x.submit(new Odd());
try {
System.out.println(f_e.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
try {
System.out.println(f_o.get());
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
x.shutdown();
}
}
class Odd implements Callable {
private int sum =0;
@Override
public Object call() {
for (int i = 0; i <= 100; i++) {
if(i%2==0){
System.out.println(Thread.currentThread().getName()+" is printing Odd numer: "+i);
sum+=i;
}
}
return sum;
}
}
class Even implements Callable{
private int sum = 0;
@Override
public Object call() {
for (int i = 0; i <= 100; i++) {
if(i%2!=0){
System.out.println(Thread.currentThread().getName()+" is printing Even numer: "+i);
sum+=i;
}
}
return sum;
}
}
运行结果:
pool-1-thread-2 is printing Odd numer: 0
pool-1-thread-2 is printing Odd numer: 2
pool-1-thread-2 is printing Odd numer: 4
pool-1-thread-2 is printing Odd numer: 6
pool-1-thread-2 is printing Odd numer: 8
pool-1-thread-2 is printing Odd numer: 10
pool-1-thread-2 is printing Odd numer: 12
pool-1-thread-2 is printing Odd numer: 14
pool-1-thread-2 is printing Odd numer: 16
pool-1-thread-2 is printing Odd numer: 18
pool-1-thread-2 is printing Odd numer: 20
pool-1-thread-2 is printing Odd numer: 22
pool-1-thread-2 is printing Odd numer: 24
pool-1-thread-1 is printing Even numer: 1
pool-1-thread-1 is printing Even numer: 3
pool-1-thread-1 is printing Even numer: 5
pool-1-thread-1 is printing Even numer: 7
pool-1-thread-1 is printing Even numer: 9
pool-1-thread-1 is printing Even numer: 11
pool-1-thread-1 is printing Even numer: 13
pool-1-thread-1 is printing Even numer: 15
pool-1-thread-1 is printing Even numer: 17
pool-1-thread-2 is printing Odd numer: 26
pool-1-thread-2 is printing Odd numer: 28
pool-1-thread-2 is printing Odd numer: 30
pool-1-thread-2 is printing Odd numer: 32
pool-1-thread-2 is printing Odd numer: 34
pool-1-thread-2 is printing Odd numer: 36
pool-1-thread-2 is printing Odd numer: 38
pool-1-thread-2 is printing Odd numer: 40
pool-1-thread-2 is printing Odd numer: 42
pool-1-thread-2 is printing Odd numer: 44
pool-1-thread-2 is printing Odd numer: 46
pool-1-thread-2 is printing Odd numer: 48
pool-1-thread-2 is printing Odd numer: 50
pool-1-thread-2 is printing Odd numer: 52
pool-1-thread-2 is printing Odd numer: 54
pool-1-thread-2 is printing Odd numer: 56
pool-1-thread-2 is printing Odd numer: 58
pool-1-thread-2 is printing Odd numer: 60
pool-1-thread-2 is printing Odd numer: 62
pool-1-thread-2 is printing Odd numer: 64
pool-1-thread-2 is printing Odd numer: 66
pool-1-thread-2 is printing Odd numer: 68
pool-1-thread-2 is printing Odd numer: 70
pool-1-thread-2 is printing Odd numer: 72
pool-1-thread-2 is printing Odd numer: 74
pool-1-thread-2 is printing Odd numer: 76
pool-1-thread-2 is printing Odd numer: 78
pool-1-thread-2 is printing Odd numer: 80
pool-1-thread-2 is printing Odd numer: 82
pool-1-thread-2 is printing Odd numer: 84
pool-1-thread-2 is printing Odd numer: 86
pool-1-thread-2 is printing Odd numer: 88
pool-1-thread-2 is printing Odd numer: 90
pool-1-thread-2 is printing Odd numer: 92
pool-1-thread-2 is printing Odd numer: 94
pool-1-thread-2 is printing Odd numer: 96
pool-1-thread-2 is printing Odd numer: 98
pool-1-thread-2 is printing Odd numer: 100
pool-1-thread-1 is printing Even numer: 19
pool-1-thread-1 is printing Even numer: 21
pool-1-thread-1 is printing Even numer: 23
pool-1-thread-1 is printing Even numer: 25
pool-1-thread-1 is printing Even numer: 27
pool-1-thread-1 is printing Even numer: 29
pool-1-thread-1 is printing Even numer: 31
pool-1-thread-1 is printing Even numer: 33
pool-1-thread-1 is printing Even numer: 35
pool-1-thread-1 is printing Even numer: 37
pool-1-thread-1 is printing Even numer: 39
pool-1-thread-1 is printing Even numer: 41
pool-1-thread-1 is printing Even numer: 43
pool-1-thread-1 is printing Even numer: 45
pool-1-thread-1 is printing Even numer: 47
pool-1-thread-1 is printing Even numer: 49
pool-1-thread-1 is printing Even numer: 51
pool-1-thread-1 is printing Even numer: 53
pool-1-thread-1 is printing Even numer: 55
pool-1-thread-1 is printing Even numer: 57
pool-1-thread-1 is printing Even numer: 59
pool-1-thread-1 is printing Even numer: 61
pool-1-thread-1 is printing Even numer: 63
pool-1-thread-1 is printing Even numer: 65
pool-1-thread-1 is printing Even numer: 67
pool-1-thread-1 is printing Even numer: 69
pool-1-thread-1 is printing Even numer: 71
pool-1-thread-1 is printing Even numer: 73
pool-1-thread-1 is printing Even numer: 75
pool-1-thread-1 is printing Even numer: 77
pool-1-thread-1 is printing Even numer: 79
pool-1-thread-1 is printing Even numer: 81
pool-1-thread-1 is printing Even numer: 83
pool-1-thread-1 is printing Even numer: 85
pool-1-thread-1 is printing Even numer: 87
pool-1-thread-1 is printing Even numer: 89
pool-1-thread-1 is printing Even numer: 91
pool-1-thread-1 is printing Even numer: 93
pool-1-thread-1 is printing Even numer: 95
pool-1-thread-1 is printing Even numer: 97
pool-1-thread-1 is printing Even numer: 99
2500
2550
Process finished with exit code 0