线程的回顾学习,个人理解学习,专业理论性知识不强
多线程
多线程是指从软硬件上实现的多条执行流程的技术
多线程创建方法
1、Thread的实现类
Thread是一个线程类,让一个子类去继承Thread,然后重写线程的run()方法,该方法就是子线程要执行的方法,然后使用线程的start()方法启动子线程;注意:main方法本身就是一个线程
先让子类继承Thread,重写run方法,方法里面我进行了5次的子线程的打印输出去,为了区分父线程和子线程的执行并发性,让线程每执行一次便休眠60ms
流程:1、继承Thread类,重写run方法。2、创建子线程对象Thread实例,执行子线程start方法启动子线程。
package com.kk.thread;
public class MyThread extends Thread{
@Override
public void run(){
for (int i = 0; i < 5 ;i++){
System.out.println("子线程MyThread执行" + i);
try {
Thread.sleep(60);//Thread的方法,让线程休眠60ms,再执行
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
main方法里,执行主线程的方法;注意一定要先执行子线程的启动,再执行主线程的方法,若是先执行主线程的逻辑,会按顺序执行完主线程的逻辑再执行子线程的逻辑,那么主线程和子线程就不是同时进行。
package com.kk.thread;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class threadTest1 {
public static void main(String[] args) throws InterruptedException {
//创建继承Thread类的子线程对象
Thread myThread = new MyThread();
//start方法启动
myThread.start();
//主线程逻辑
for (int i = 0; i < 5 ; i ++){
System.out.println("父线程main执行" + i);
Thread.sleep(60);
}
}
}
运行结果如下:
可以看出主线程和子线程在并发执行
一旦先执行主线程的逻辑再执行子线程就会出现下面结果:是错误的
2、Runable接口的实现
我们可以通过实现Runable接口,创建一个实现类对象,可以将实现类对象理解为任务类对象,将任务交给线程去执行,以此来实现多线程。Runable接口只有一个run方法,所以实现类重写的run方法就是子线程要执行的逻辑、任务。
流程:1、实现Runable接口,重写run方法。2、创建实现类对象将其交给Thread实例执行start,启动子线程。3、执行主线程逻辑
1、实现Runable接口,重写run方法
package com.kk.thread;
public class MyRunable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i ++ ){
System.out.println("Runable实现类线程执行" + i);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
2、创建实现类对象将其交给Thread实例执行start,启动子线程。3、执行主线程逻辑
package com.kk.thread;
public class MyThreadTest2 {
public static void main(String[] args) throws InterruptedException {
//创建Runable实现类对象
MyRunable myRunable = new MyRunable();
//将其交给Thread
Thread thread = new Thread(myRunable);
//启动线程
thread.start();
//主线程逻辑
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行" + i);
Thread.sleep(30);
}
}
}
执行结果如下:
3、Callable接口的实现
前两种实现多线程的方法都无法返回子线程执行后的结果,而Callable接口的实现可以返回执行后的结果。
Callable接口的实现类去重写其call方法,再将Callable的实现类对象封装成FutureTask对象,FutureTask是实现了Runable接口的,然后将FutureTask对象交给Thread实例去执行start方法,启动线程即可。Callable是泛型接口,可以执行返回值的类型
流程:1、Callable接口的实现,重写call方法。2、封装Callable实现类对象为FutureTask对象。3、将封装后的对象FutureTask对象交给Thread实例执行start方法,启动子线程。
1、Callable接口的实现,重写call方法
package com.kk.thread;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer> {
private int n;
//利用构造器实现传参
public MyCallable(int n){
this.n = n;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1 ; i <= n ; i ++){
sum += i;
}
return sum;
}
}
2、封装Callable实现类对象为FutureTask对象。
3、将封装后的对象FutureTask对象交给Thread实例执行start方法,启动子线程
package com.kk.thread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyThreadTest3 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//将Callable实现类对象封装成FutureTask对象
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable(10));
//将FutureTask对象交给Thread实例执行start方法
new Thread(futureTask).start();
//通过FutureTask对象的get方法得到返回值
Integer returnValue = futureTask.get();
System.out.println(returnValue);
}
}
执行结果如下:
3.13