多线程概述及其三种创建方式
创建方式一 继承Thread类
代码演示一下线程的创建和使用:
图中主线程和t线程一起在跑,每次运行程序可以发现主线程和t线程之间输出的交叉顺序是随机的,说明是多线程运行。
创建方式二 实现Runnable接口
创建方式三 利用Callable接口、FutureTask类来实现
/**
* 1、让这个类实现Callable接口
*/
public class MyCalllable implements Callable<String> {
public MyCalllable(int n) {
this.n = n;
}
private int n;
// 2、重写call方法
@Override
public String call() throws Exception {
//描述线程的任务,返回线程执行后的结果
//需求:求1-n的和返回
int sum=0;
for (int i = 1; i <= n; i++) {
sum+=i;
}
return "线程求出了1-"+ n + "的和是:" + sum;
}
}
/**
* 目标:掌握线程的创建方式三:实现Callable接口
*/
public class main {
public static void main(String[] args) throws Exception {
//3、创建一个Callable的对象
Callable<String> call = new MyCalllable(100);
//4、把Callable对象封装成一个FutureTask对象(任务对象)
//未来对象的作用?
//(1) 是一个任务对象,实现了Runnable接口
//(2) 可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕之后的返回值
FutureTask<String> f1 = new FutureTask<>(call);
//5、把任务对象交给一个Thread对象
new Thread(f1).start();
//6、获取线程执行完毕之后返回的结果
//注意:如果主线程执行到这,假如上面的线程还没有执行完毕
//则这里的代码会暂停,等待上面的线程执行完毕之后返回结果
String rs = f1.get();
System.out.println(rs);
}
}
线程的常用方法
下面我们演示一下这些方法的使用效果。
public class MyThread extends Thread{
public MyThread() {
}
public MyThread(String name){
super(name); //1.执行父类Thread(String name)构造器,为当前线程设置名字了
//相当于在main里执行t3.setName("3号线程") 设置线程名称;
}
@Override
public void run() {
//2.currentThread() 哪个线程执行它,它就会得到哪个线程对象。
Thread t = Thread.currentThread();
for (int i = 1; i <= 3; i++) {
//3.getName() 获取线程名称
System.out.println(t.getName() + "输出:" + i);
}
}
}
public static void main(String[] args) throws Exception {
Thread t1 = new MyThread();
t1.start();
System.out.println(t1.getName());//Thread-0(默认线程名,如果下面t2不设置名字将是Thread-1)
Thread t2 = new MyThread("2号线程");
t2.start();
System.out.println(t2.getName()); // 2号线程
Thread t3 = new MyThread();
t3.setName("3号线程");
t3.start();
System.out.println(t3.getName()); // 3号线程
// 输出主线程对象的名字
// 哪个线程执行下面的函数,它就会得到哪个线程对象。
Thread m = Thread.currentThread();
System.out.println(m.getName()); // main
m.setName("最牛的线程");
System.out.println(m.getName()); // 最牛的线程
for (int i = 1; i <= 5; i++) {
System.out.println(m.getName() + "线程输出:" + i);
}
}
main的执行结果为:
Thread-0
2号线程
3号线程
main
最牛的线程
最牛的线程线程输出:1
Thread-0输出:1
2号线程输出:1
3号线程输出:1
2号线程输出:2
Thread-0输出:2
最牛的线程线程输出:2
Thread-0输出:3
2号线程输出:3
3号线程输出:2
最牛的线程线程输出:3
3号线程输出:3
最牛的线程线程输出:4
最牛的线程线程输出:5
最后再演示一下join这个方法是什么效果。
public class ThreadTest2 {
public static void main(String[] args) throws Exception {
// join方法作用:让当前调用这个方法的线程先执行完。
Thread t1 = new MyThread("1号线程");
t1.start();
t1.join();
Thread t2 = new MyThread("2号线程");
t2.start();
t2.join();
Thread t3 = new MyThread("3号线程");
t3.start();
t3.join();
}
}
执行效果是1号线程先执行完,再执行2号线程;2号线程执行完,再执行3号线程。
还有sleep方法: