Java实现多线程的方式有比较多,但究其本质,最终都是在执行Thread的run方法,这个后文再作解释。下面先看看各种实现方式。
- public class RunnableThread implements Runnable{
- @Override
- public void run() {
- System.out.println("Runnable接口实现线程");
- }
-
- public static void main(String[] args) {
- new Thread(new RunnableThread()).start();
- }
- }
通过实现 Runnable 接口实现多线程,只需要重写run接口,然后将Runnable实例传递给Thread类,调用start即可启动线程。
- public class ExtendsThread extends Thread {
-
- @Override
- public void run() {
- System.out.println("用Thread类实现线程");
- }
-
- public static void main(String[] args) {
- new ExtendsThread().start();
- }
- }
继承 Thread 类实现多线程,这种方式直接重写Thread类的run方法,同样通过start方法启动多线程。
还可以通过线程池创建线程,方式参考如下
- /**
- * @author kangming.ning
- * @date 2023-02-24 16:27
- * @since 1.0
- **/
- public class CustomThreadPool1 {
-
- private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNamePrefix("线程池-").build();
-
- private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
- Runtime.getRuntime().availableProcessors(),
- Runtime.getRuntime().availableProcessors() * 2,
- 60L,
- TimeUnit.SECONDS,
- new LinkedBlockingQueue<>(10),
- threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
-
- public static void main(String[] args) throws InterruptedException {
- Runnable r = () -> {
- System.out.println(Thread.currentThread().getName() + " is running");
- };
- for (int i = 0; i < 35; i++) {
- Thread.sleep(1000);
- threadPoolExecutor.submit(r);
- }
- }
-
- }
当然,也可以使用ExecutorService去管理线程池,这个方式和上面的没本质区别,ExecutorService实际也是使用ThreadPoolExecutor创建的线程池,如下:
- public class FixedThreadPool {
- public static void main(String[] args) {
- ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
- for (int i = 0; i < 5; i++) {
- executor.execute(new RunnableThread());
- }
- executor.shutdown();
- }
- }
-
- public class RunnableThread implements Runnable {
- @Override
- public void run() {
- System.out.println("用实现Runnable接口实现线程,ThreadName:" + Thread.currentThread().getName());
- }
- }
- public class CallableTask implements Callable
{ - @Override
- public Integer call() throws Exception {
- return new Random().nextInt();
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- //创建线程池
- ExecutorService service = Executors.newFixedThreadPool(10);
- //提交任务,并用Future提交返回结果
- Future
future = service.submit(new CallableTask()); - Integer randomNumber = future.get();//此方法阻塞
- System.out.println("randomNumber:"+randomNumber);
- service.shutdown();
- }
- }
- public class TimerTest {
- public static void main(String[] args) {
- Timer timer=new Timer();
- //延时0毫秒 每1秒执行一次
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- System.out.println("Timer线程,ThreadName:"+Thread.currentThread().getName());
- }
- },0,1000);
- }
- }
定时器Timer内部使用TimerThread处理定时任务,TimerThread继承于Thread类,于是,还是之前方式,只是包装了一下。
通过上面的讲述,我们发现,看似有很多方式去实现多线程,但最终都需要通过Thread类,调用start方法,实现线程的开启。下面看一下Thread类的start方法
- /* What will be run. */
- private Runnable target;
-
- public synchronized void start() {
- /**
- * This method is not invoked for the main method thread or "system"
- * group threads created/set up by the VM. Any new functionality added
- * to this method in the future may have to also be added to the VM.
- *
- * A zero status value corresponds to state "NEW".
- */
- if (threadStatus != 0)
- throw new IllegalThreadStateException();
-
- /* Notify the group that this thread is about to be started
- * so that it can be added to the group's list of threads
- * and the group's unstarted count can be decremented. */
- group.add(this);
-
- boolean started = false;
- try {
- start0();
- started = true;
- } finally {
- try {
- if (!started) {
- group.threadStartFailed(this);
- }
- } catch (Throwable ignore) {
- /* do nothing. If start0 threw a Throwable then
- it will be passed up the call stack */
- }
- }
- }
-
- private native void start0();
-
- @Override
- public void run() {
- if (target != null) {
- target.run();
- }
- }
可以看出,start方法最终会经由start0本地方法最终调用run方法。而run方法里面的target是一个Runnable对象,如果target不是空,就调用target的run方法。这就解释了为什么实现Runnable接口传递给Thread构造函数,最终能调用Runnable的run方法。如果我们用继承Thread重写run方法来实现线程,明显,start方法调用的run方法直接就是这个子类的run方法了。这样看来,实现多线程只有一种方法,就是构造Thread类,调用start方法,经由本地方法start0最终调用它的run方法。