Java多线程的三种实现方式与Thread常用API
一、继承Thread类的方式进行实现
实现步骤:
1.自己定义一个类继承Thread
2.重写Run方法
3.创建子类的对象并启动线程
public class Demo {
/**
* 多线程的第一种启动方式:
* 1.自己定义一个类继承Thread
* 2.重写Run方法
* 3.创建子类的对象并启动线程
*/
public static void main(String[] args) {
Case case1=new Case();//创建对象1
Case case2=new Case();//创建对象2
case1.setName("线程1");//为线程取名字
case2.setName("线程2");//为线程取名字
case1.start();//3.启动线程1
case2.start();//3.启动线程2
}
//1.定义Case类继承Thread
public static class Case extends Thread{
@Override
//2.重写run方法
public void run() {
//getName()为获取当前线程名称
for (int i = 0; i < 100; i++) {
System.out.println(getName()+"实现"+i);
}
}
}
}
★该方法使用Lambda表达式进行简化
//该实现可以用Lambda表达式进行简化 如下
new Thread(()->{
for (int i = 0; i < 100; i++) {
System.out.println("线程1实现"+i);
}
}).start();
new Thread(()->{
for (int i = 0; i < 100; i++) {
System.out.println("线程2实现"+i);
}
}).start();
二、实现Runnable接口的方式进行实现
实现步骤:
1.自己定义一个类实现Runnalble接口
2.重写run方法
3.创建一个Thread类对象,并开启线程
public class Demo2 {
/**
* 多线程第二种启动方式
* 1.自己定义一个类实现Runnalble接口
* 2.重写run方法
* 3.创建一个Thread类对象,并开启线程
*/
public static void main(String[] args) {
//创建Case对象,表示多线程要执行的任务
Case case1=new Case();
//3.创建线程(Thread)对象
Thread t1=new Thread(case1,"线程1");
Thread t2=new Thread(case1,"线程2");
t1.start();//启动线程1
t2.start();//启动线程2
}
//1.新建一个类实现Runnable接口
public static class Case implements Runnable{
@Override
//2.重写run方法
public void run() {
//获取当前线程的名字
String name=Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
System.out.println(name+"实现"+i);
}
}
}
}
★该方法使用Lambda表达式进行简化
//该实现可以用Lambda表达式进行简化 如下
// 通过Lambda表达式创建匿名的Runnable对象,定义线程任务
Runnable task = () -> {
//获取当前线程的名字
String name=Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
System.out.println(name+"实现"+i);
}
};
// 创建Thread对象,将上面创建的Runnable对象作为参数传入
new Thread(task,"线程1").start();
new Thread(task,"线程2").start();
三、利用Callable接口和Future接口方式实现
特点:可以获取到多线程的执行结果
1.自己定义一个类实现Callable接口,并提供返回值类型(泛型的位置)
2.重写call()方法(是有返回值的,表示多线程运行的结果)
3.创建FutureTask对象(作用管理多线程的结果)
4.创建Thread类的对象,并启动(表示线程)
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo3 {
/**
* 多线程第三种启动方式
* 特点:可以获取到多线程的执行结果
* 1.自己定义一个类实现Callable接口,并提供返回值类型(泛型的位置)
* 2.重写call()方法(是有返回值的,表示多线程运行的结果)
* 3.创建FutureTask对象(作用管理多线程的结果)
* 4.创建Thread类的对象,并启动(表示线程)
*/
public static void main(String[] args) {
//实例化我们定义的对象
Case case1=new Case();
//创建FutreTask对象(作用管理多线程的结果)
//注意泛型的类型要一致
FutureTask<String> ft=new FutureTask<>(case1);
Thread t1=new Thread(ft,"线程");
t1.start();//启动线程1
//获取多线程运行的结果 记得要捕获一下异常
try {
//获取多线程运行结果并打印
String result1= ft1.get();
System.out.println(result1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
//自己定义一个类实现Callable接口
//我这边用返回值设置为String
public static class Case implements Callable<String> {
@Override
public String call() throws Exception {
//求1~100之间的和
int sum=0;
for (int i = 1; i <=100 ; i++) {
sum+=i;//子增加i
}
//返回当前线程的名称+最终求和结果
return Thread.currentThread().getName()+":"+sum;
}
}
}
★该方法使用Lambda表达式进行简化
//该实现可以用Lambda表达式进行简化 如下
//
FutureTask<String> ft1=new FutureTask<>(()->{
//求1~100之间的和
int sum=0;
for (int i = 1; i <=100 ; i++) {
sum+=i;//子增加i
}
//返回当前线程的名称+最终求和结果
return Thread.currentThread().getName()+":"+sum;
});
new Thread(ft1).start();
System.out.println(ft1);
★三种实现方式的区别:
①继承Thread类
优点:编程比较简单,可以直接使用Thread类中的方法
缺点:可以扩展性较差,不能再继承其他的类,无返回数据②实现Runnable接口
优点:扩展性强,实现该接口的同时还可以继承其他的类
缺点:编程相对复杂,不能直接使用Thread类中的方法③实现Callable接口
优点:扩展性强,实现该接口的同时还可以继承其他的类,可定义返回数据
缺点:编程相对复杂,不能直接使用Thread类中的方法
★Thread常用API
1.Thread(Runnable target): 创建一个新的线程对象,并指定它要执行的Runnable对象
2.start(): 启动一个线程
3.run(): 用于定义线程的主体,当线程被启动时,该方法自动调用
4.join([timeout]): 插入线程/插队线程
//join插入线程使用示例:
//不加插入线程的话main线程永远是执行在最前面的
//加入join插入线程后,main线程执行在后面了
public static void main(String[] args) {
Thread t=new Thread(()->{
for (int i = 0; i < 100; i++) {
String name=Thread.currentThread().getName();
System.out.println(name+":@"+i);
}
},"飞机");
t.start();
try {
t.join();//将t线程插入到main线程前
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < 10; i++) {
System.out.println("min线程:"+i);
}
}
5.isAlive(): 检查线程是否正在运行
6.currentThread(): 获取当前线程对象
7.yield(): 让出CPU控制权,让出线程/礼让线程
//yield礼让线程示例
public static void main(String[] args) {
new Thread(() -> function(),"飞机").start();
new Thread(() -> function(),"坦克").start();
}
public static void function(){
String name=Thread.currentThread().getName();
for (int i = 0; i < 100; i++) {
System.out.println(name+":@" + i);
Thread.yield();//出让线程
//作用:使得两个线程执行尽可能的均匀
//注意:不是绝对均匀,是尽可能的均匀
}
}
8.sleep(long millis): 使当前线程休眠指定的毫秒数
9.interrupt(): 中断该线程的阻塞状态
10.setPriority(int priority): 设置线程的优先级 可设置1-10(默认为5)
11.getPriority(): 获取线程优先级
12.setDaemon(): 设置为守护线程(备胎模式)
//守护线程 示例
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("女神:@" + i);
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
System.out.println("备胎:@" + i);
}
});
t2.setDaemon(true);//设置为守护模式
//守护没有设置Daemon的线程,当没有设置Daemon的线程结束后
//设置了Daemon的线程运行一段后,自行结束
t1.start();
t2.start();
13.getState(): 获取线程的状态,如NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED
14.wait(): 使当前线程等待,直到其他线程调用notify()或者notifyAll()方法唤醒它。
15.notify(): 唤醒一个等待中的线程
16.notifyAll(): 唤醒所有等待中的线程
发表评论