从Java创建线程入门多线程

本文是Java多线程系列的第一篇文章,关于线程的基础知识这里不多介绍,在我之前的文章中就已经介绍过了,不熟悉什么是线程的同学可以先去看一下。操作系统-进程与线程

从最老生常谈的Java创建线程方式谈起

稍微了解过一点Java多线程编程的朋友一定知道,Java创建线程的方式一般有三种:重写Thread类、实现Runnable和实现Callable接口,当然线程池也算是创建线程的一种方式,但那就扯远了,我们暂时从这三种方式聊起。

重写Thread类

public class CreateThreadTest {
	public static void main(String[] args) {
		MyThread t = new MyThread();
		t.start();
	}
}

class MyThread extends Thread {
	@Override
	public void run() {
		System.out.println("do something here...");
	}
}

很简单的方式,重写Thread类的demo上面已给出。

实现Runnable接口

public class CreateThreadTest {
	public static void main(String[] args) {
		Thread t = new Thread(new MyRunnable());
		t.start();
	}
}

class MyRunnable implements Runnable {
	@Override
	public void run() {
		System.out.println("do something here...");
	}
}

同样很简单,实现Runnable接口后将MyRunnable对象传给Thread类。

实现Callable接口

public class CreateThreadTest {
	public static void main(String[] args) {
		FutureTask<Boolean> result = new FutureTask<>(new MyCallable());
		Thread t = new Thread(result);
		t.start();
		try {
			System.out.println(result.get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
	}
}

class MyCallable implements Callable<Boolean> {
	@Override
	public Boolean call() throws Exception {
		System.out.println("do something here...");
		return true;
	}
}

实现Callable接口这种方式与实现Runnable接口的不同之处在于多了一个返回值。

start()和run()到底有什么区别

首先需要明确的是,start()是一个native方法,该方法会启动一个线程,线程执行run()方法里的内容。与直接执行run()方法不同的是,start()会启动一个新的线程,这个线程与主线程并发执行。如果直接执行线程的run()方法就不会启动新的线程,相当于执行了一个普通方法。

关于run()方法的细节

run()方法作为创建线程的核心,我们这里就来扒一扒源码。

首先是Thread类的run()方法,代码如下:

private Runnable target;

@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

很显然,Thread类中的run()方法就是调用Runnable对象的run()方法,我们再看一下Runnable接口的源码。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Runnable接口很简单,就是一个run()抽象方法。在Runnable接口上有个@FunctionalInterface注解,表明可以实现函数式编程。

如果既继承了Thread类又实现了Runnable接口呢?

有没有想过当一个线程既继承了Thread类又实现了Runnable接口会执行哪个run()方法?

public class CreateThreadTest {
	public static void main(String[] args) {
		Thread t = new Thread(() -> System.out.println("Runnable method")) {
			@Override
			public void run() {
				System.out.println("Thread method");
			}
		};
		t.start();
	}
}

大家觉得上面的代码会怎么执行?答案是执行匿名内部类中的方法,也就是打印Thread method。回顾一下之前分析的源码就不难知道,在Thread中执行的是target对象的run()方法,而这里我们在匿名内部类中重写了run()方法,与原来的父类run()方法已经没有关系了,自然也不会运行target对象的run()方法。

你可能感兴趣的:(Java)