网站单页推广,廊坊做网站外包,什么网站可以找到手工活做,伊犁州建设局网站Java 有三种方式实现多线程#xff0c;继承 Thread 类、实现 Runnable 接口、实现 Callable 接口。还有匿名内部类方式#xff0c;Lambda 表达式方式简化开发。
1、Thread
Thread 创建线程方式#xff1a;创建线程类 start() 方法底层其实是给 CPU 注册当前线程#xff0…Java 有三种方式实现多线程继承 Thread 类、实现 Runnable 接口、实现 Callable 接口。还有匿名内部类方式Lambda 表达式方式简化开发。
1、Thread
Thread 创建线程方式创建线程类 start() 方法底层其实是给 CPU 注册当前线程并且触发 run() 方法执行 线程的启动必须调用 start() 方法如果线程直接调用 run() 方法相当于变成了普通类的执行此时主线程将只有执行该线程 建议线程先创建子线程主线程的任务放在之后否则主线程main永远是先执行完
Thread 构造器 public Thread() public Thread(String name)
public class p1 {public static void main(String[] args) {// 创建线程类方式Thread t1 new MyThread();t1.start();}
}
class MyThread extends Thread{Overridepublic void run() {for(int i 0 ; i 100 ; i ) {// 子线程输出System.out.println(Thread.currentThread().getName() - i);}}
}
继承 Thread 类的优缺点 优点编码简单 缺点线程类已经继承了 Thread 类无法继承其他类了功能不能通过继承拓展单继承的局限性
2、Runnable
Runnable 创建线程方式创建线程类
Thread 的构造器 public Thread(Runnable target) public Thread(Runnable target, String name)
public class p2 {public static void main(String[] args) {Runnable target new MyRunnable();Thread t1 new Thread(target,Runnable线程);t1.start();Thread t2 new Thread(target);//Thread-0}
}public class MyRunnable implements Runnable{Overridepublic void run() {for(int i 0 ; i 10 ; i ){System.out.println(Thread.currentThread().getName() - i);}}
}
Thread 类本身也是实现了 Runnable 接口Thread 类中持有 Runnable 的属性执行线程 run 方法底层是调用 Runnable#run public class Thread implements Runnable {private Runnable target;public void run() {if (target ! null) {// 底层调用的是 Runnable 的 run 方法target.run();}}}
Runnable 方式的优缺点 缺点代码复杂一点。 优点 线程任务类只是实现了 Runnable 接口可以继续继承其他类避免了单继承的局限性 同一个线程任务对象可以被包装成多个线程对象 适合多个多个线程去共享同一个资源 实现解耦操作线程任务代码可以被多个线程共享线程任务代码和线程独立 线程池可以放入实现 Runnable 或 Callable 线程任务对象
3、Callable
实现 Callable 接口 定义一个线程任务类实现 Callable 接口申明线程执行的结果类型 重写线程任务类的 call 方法这个方法可以直接返回执行的结果 创建一个 Callable 的线程任务对象 把 Callable 的线程任务对象包装成一个未来任务对象 把未来任务对象包装成线程对象 调用线程的 start() 方法启动线程 public FutureTask(CallableV callable)未来任务对象在线程执行完后得到线程的执行结果 FutureTask 就是 Runnable 对象因为 Thread 类只能执行 Runnable 实例的任务对象所以把 Callable 包装成未来任务对象
public V get()同步等待 task 执行完毕的结果如果在线程中获取另一个线程执行结果会阻塞等待用于线程同步 get() 线程会阻塞等待任务执行完成 run() 执行完后会把结果设置到 FutureTask 的一个成员变量get() 线程可以获取到该变量的值
public class p3 {public static void main(String[] args) {CallableString call new MyCallable();FutureTaskString task new FutureTask(call);Thread t1 new Thread(task);t1.start();try {// 获取call方法返回的结果正常/异常结果String s task.get(); System.out.println(s);} catch (Exception e) {e.printStackTrace();}}public class MyCallable implements CallableString {Overridepublic String call() throws Exception {return Thread.currentThread().getName() - MyCallable String;}
}
优缺点 优点同 Runnable并且能得到线程执行的结果 缺点编码复杂
4、匿名内部类方式、Lambda 表达式方式
public class p1 {public static void main(String[] args) {// 匿名内部类方式Thread t1 new Thread(new Runnable() {Overridepublic void run() {System.out.println(t1 线程执行中);}});t1.start();// Lambda 表达式创建匿名内部类的线程对象Thread t2 new Thread(() - {System.out.println(t2 线程执行中);});t2.start();}
}
使用匿名内部类的方式可以方便地定义并实例化线程对象并实现线程的执行逻辑。它对于一些简单的线程任务可以简洁地表达但对于复杂的线程逻辑建议使用具名的内部类或者单独定义一个类来实现Runnable接口。
使用 lambda 表达式代替了匿名内部类使得代码更加简洁。适用于只包含一个抽象方法的接口例如 Runnable 接口和 Callable 接口。对于其他接口如果包含多个抽象方法就无法使用 lambda 表达式来创建匿名内部类。 借鉴https://github.com/Seazean/JavaNote/blob/main/Prog.md