一.多线程
1.继承Thread类
public class MyThread extends Thread{
private int ticket = 5;
@Override
public void run() {
for(int i = 0; i < ticket; i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName()+"卖票:" + ticket--);
}
}
}
}
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread.start();
myThread1.start();
myThread2.start();
}
}
结果:
Thread-1卖票:5
Thread-0卖票:5
Thread-0卖票:4
Thread-0卖票:3
Thread-0卖票:2
Thread-0卖票:1
Thread-1卖票:4
Thread-1卖票:3
Thread-1卖票:2
Thread-1卖票:1
Thread-2卖票:5
Thread-2卖票:4
Thread-2卖票:3
Thread-2卖票:2
Thread-2卖票:1
2.实现Runnble接口
public class MyRunable implements Runnable{
private int ticket = 5;
@Override
public void run() {
for(int i = 0; i < 100; i++){
if(ticket > 0){
System.out.println(Thread.currentThread().getName()+"买票:"+ticket--);
}
}
}
}
public class Main {
public static void main(String[] args) {
MyRunable myRunable = new MyRunable();
Thread thread1 = new Thread(myRunable);
Thread thread2 = new Thread(myRunable);
Thread thread3 = new Thread(myRunable);
thread1.start();
thread2.start();
thread3.start();
}
}
结果:
Thread-0买票:5
Thread-0买票:3
Thread-0买票:2
Thread-1买票:4
Thread-2买票:1
3.两者的区别与联系
a.继承类和实现接口的区别(单继承:一个类只能继承一个类,多实现:一个类可以实现多个接口)
b.Runable接口是资源共享的,所有线程共同完成一件事,有可能一个线程完成所有事,也有可能每个线程干一件事。而Thread类,各干各的。如上面的示例。
c.在客户端调用实现了Runnable接口的线程,实际采用的是代理模式。查看Thread类的源码:
class Thread implements Runnable {
@Override
public void run() {
if (target != null) {
target.run();
}
}
}
客户端调用:
public class Main {
public static void main(String[] args) {
MyRunable myRunable = new MyRunable();//原对象
Thread thread1 = new Thread(myRunable);//代理对象
thread1.start();
}
}
代理模式具体参考:https://blog.csdn.net/qinqinde123/article/details/88836819
二.线程池
1.线程池的作用
a.减少了每次创建线程、销毁线程的开销
b.提高响应速度 ,每次请求到来时,由于线程的创建已经完成,故可以直接执行任务
c.提高线程的可管理性:
2.线程池调度过程:提交的任务是放在LinkedBlockingQueue中,由Executor来调度。
3.线程池中任务分类:Runnable和Callable
Callable:该类任务有返回结果,可以抛出异常。 通过submit函数提交,返回Future对象。 可通过get获取执行结果。
Runnable: 该类任务只执行,无法获取返回结果,并在执行过程中无法抛异常。 通过execute提交.
4.线程池分类:
a.FixedThreadPool 定长线程池:初始化的时候,线程池中的线程已经创建好,一旦LinkedBlockingQueue中有任务,Executor会从线程池中调度一个线程去执行此任务,当该任务执行完毕之后,对应的线程释放,重新回到线程池,等待下一次调度。线程池中的线程永远不会被kill掉。
b.CachedThreadPool 可缓存线程池: 线程池的大小不固定(最小是0,最大可以为无限大),初始化的时候,线程池中的线程数为0。当有任务出现,先判断线程池中是否有空闲线程,如果有,则执行任务,如果没有,则在线程池中创建新的线程。当任务执行完毕之后,释放该线程,等待keepAliveTime秒之后,如果此线程没有被分配任务,则kill掉。
c.SingleThreadExecutor 单一线程池: 只会创建一条工作线程处理任务,采用的阻塞队列为LinkedBlockingQueue
d.ScheduledThreadPool 可调度的线程池: 处理延时任务或定时任务,采用的DelayQueue来管理任务。
5.线程池用法
a.Callable用法
public class ThreadPoolCallable implements Callable<String>{
private int count;
public ThreadPoolCallable(int count) {
this.count = count;
}
@Override
public String call() throws Exception {
return "hello world" + count;
}
}
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
List<Future<String>> futures = new ArrayList<>();
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 5; i++){
Future<String> future = executor.submit(new ThreadPoolCallable(i));
futures.add(future);
}
if(null != executor){
executor.shutdown();
}
for(Future<String> future:futures){
System.out.println(future.get());
}
}
}
b.Runable用法
public class ThreadPoolRunable implements Runnable{
@Override
public void run() {
try{
System.out.println("task is running...");
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
for(int i = 0; i < 5; i++){
executor.execute(new ThreadPoolRunable());
}
}
}
6.通过线程池批量提交任务invokeAll
a.通过定义Callable类型的线程
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(4);
List<ThreadPoolCallable> tasks = new ArrayList<>();
for(int i = 0; i < 4; i++){
tasks.add((new ThreadPoolCallable(i)));
}
List<Future<String>> futures = executor.invokeAll(tasks);
for(Future<String> future : futures){
System.out.println(future.get());
}
}
}
b.没有定义Callable类时:
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Callable<List<? extends Object>>> tasks = new ArrayList<>();
for(int i = 0; i < 4; i++){
tasks.add(new Callable<List<? extends Object>>() {
@Override
public List<? extends Object> call() throws Exception {
return Arrays.asList("1","2","3");
}
});
}
List<Future<List<? extends Object>>> futures = executor.invokeAll(tasks);
for(Future<List<? extends Object>> future : futures){
System.out.println(future.get());
}
}
}
c.转换成更简单的lambda表达式
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(4);
List<Callable<List<? extends Object>>> tasks = new ArrayList<>();
for(int i = 0; i < 4; i++){
tasks.add((Callable)()->{
return Arrays.asList("1","2","3");
});
}
List<Future<List<? extends Object>>> futures = executor.invokeAll(tasks);
for(Future<List<? extends Object>> future : futures){
System.out.println(future.get());
}
}
}