Java线程一共6个状态。
package chapter09;public class Java01_Thread {public static void main(String[] args) {// TODO 线程// Thread是线程类// currentThread 方法用于获取当前正在运行的线程// getName 方法获取线程的名字// main方法运行在main线程中
// System.out.println(Thread.currentThread().getName());
//
// // todo 创建线程
Thread t = new Thread();
// MyThread t = new MyThread();
// // todo 启动线程
// t.start();
//
// System.out.println(Thread.currentThread().getName());// todo 构建线程对象时,可以只把逻辑传递给这个对象// 传递逻辑时,需要遵循规则: () -> { 逻辑 }// ()->{} 是一个 lambda 表达式。它实现了 Runnable 接口的 run 方法// Runnable 接口是一个函数式接口(只有一个抽象方法的接口),因此可以使用 lambda 表达式来简化代码。// Lambda 表达式 简化了函数式接口的实现,使代码更简洁。// 等价写法 可以使用匿名内部类来实现Thread thread1 = new Thread(() -> {System.out.println("线程执行1");});// 等价于下面的写法// 构建线程对象时,可以传递实现了Runnable接口的对象,一般使用匿名类// Thread thread1 = new Thread(new Runnable() {// @Override// public void run() {// System.out.println("线程执行1");// }//});thread1.start();}
}// TODO 声明自定义线程类
class MyThread extends Thread {@Overridepublic void run() {System.out.println("MyThread :" + Thread.currentThread().getName());}
}
package chapter09;import java.io.IOException;public class Java02_多线程 {public static void main(String[] args) throws InterruptedException {// TODO 多线程 - 执行方式 (串行,并发)// 并发执行:多个线程是独立的,谁抢到CPU执行权,谁就能执行
// int i = 0;
// while (i++ < 100) {
// MyThread1 t1 = new MyThread1();
// MyThread2 t2 = new MyThread2();
// t1.start();
// t2.start();
// System.out.println("xxxxxxxxxxxx\n");
// }// 串行执行:多个线程连接成串,然后按照顺序执行int i = 0;while (i++ < 100) {MyThread1 t1 = new MyThread1();MyThread2 t2 = new MyThread2();t1.start();t2.start();// 将线程连接成串t1.join();t2.join();System.out.println("xxxxxxxxxxxx\n");}}
}class MyThread1 extends Thread {@Overridepublic void run() {System.out.println("MyThread1 :" + Thread.currentThread().getName());}
}class MyThread2 extends Thread {@Overridepublic void run() {System.out.println("MyThread2 :" + Thread.currentThread().getName());try {Thread.sleep(1000); // 休眠1秒钟} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
四种常见的线程池
package chapter09;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Java05_Thread_Pool {public static void main(String[] args) {// TODO 线程 - 线程池// 所谓线程池,其实就是线程对象的容器// 可以根据需要,在启动时,创建一个或多个线程对象// Java中有4种比较常见的线程池// 1. 创建固定数量的线程对象// ExecutorService是线程服务对象ExecutorService executorService = Executors.newFixedThreadPool(3);// 2. 根据需求动态创建线程, 创建的线程可以重复使用,只是当目前线程不够了他会动态增加线程executorService = Executors.newCachedThreadPool();// 3. 单一线程executorService = Executors.newSingleThreadExecutor();// 4. 定时调度线程, 线程有3个,但是线程在什么时候执行我们可以去定义他executorService = Executors.newScheduledThreadPool(3);for (int i = 0; i < 5; i++) {executorService.submit(new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName());}});}}
}
在 Java 中,创建并启动一个新的线程通常有两种主要的方式:继承 Thread 类和实现 Runnable 接口。
- 通过继承 Thread 类来创建一个新的线程类,并重写 Thread 类的 run() 方法。
class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread is running");}public static void main(String[] args) {MyThread t = new MyThread();t.start(); //启动线程}
}
- 通过实现 Runnable 接口并实现其 run() 方法,然后将 Runnable 实例传递给 Thread 对象。
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Thread is running");}public static void main(String[] args) {MyRunnable r = new MyRunnable();Thread t = new Thread(r);t.start();}
}
特性 | 继承 Thread 类 | 实现 Runnable 接口 |
---|---|---|
继承 | 不支持多继承,限制较大 | 支持多继承,更灵活 |
代码解耦 | 线程逻辑和线程控制耦合 | 线程逻辑和线程控制分离 |
复用性 | 不易复用 | 更易复用 |
共享资源 | 需要额外处理 | 自然适应共享资源 |
ps:若两个同时使用呢?
class BothRunnableThread {public static void main(String[] args) {// 创建一个匿名内部类实现 Runnable 接口的 run 方法new Thread(new Runnable() {@Overridepublic void run() {// 这个 run 方法来自于 Runnable 接口System.out.println("I am runnable");}}) {// 创建一个匿名内部类继承 Thread 类并重写其 run 方法@Overridepublic void run() {// 这个 run 方法来自于 Thread 类System.out.println("I am thread");}}.start(); // 启动线程}
}
结果是:
原因:
创建了一个实现了 Runnable 接口的匿名内部类的对象,然后这个Runnable类的匿名内部类的对象被传给Thread的target。
但是Thread的下面三行run方法被重写了,也就不用管Runnable类的target了,虽然Runnable类的target的run方法被重写了,所以没机会执行Runnable类的target的run方法了。