一)继承Runnable接口
Runnable接口简介:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
@FunctionalInterface:函数式接口,有以下几个特点。
1)接口中有且仅有一个抽象方法。
2)可允许定义静态方法和默认方法。
3)允许java.lang.Object中的public方法。
4)该注解不是必须的,只要符合“函数式接口”即可,加上该注解能让编译器更好检查。如不符合规则,又添加该注解,编译器就会报错。
实现步骤:
第一步:自定义一个类,继承Runnable接口。
第二步:重写run()方法。
方式一:通过Thread类构造Runnable实现。
public class MyOneRunnable implements Runnable {
// 通过构造函数的方式,指定一个变量
private String threadName;
public MyOneRunnable(String threadName) {
this.threadName = threadName;
}
public void run() {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable: " + threadName + ", i=" + i);
Thread.sleep((int)(Math.random()*100)); // 随机睡眠指定毫秒
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyOneRunnable r1 = new MyOneRunnable("Thread 1");
Thread thread1 = new Thread(r1);
thread1.start();
MyOneRunnable r2 = new MyOneRunnable("Thread 2");
Thread thread2 = new Thread(r2);
thread2.start();
}
}
打印效果图:
方式二:通过Thread类实现,并指定运行线程的名称。
public class MyTwoRunnable implements Runnable {
private Thread thread;
private String threadName;
public MyTwoRunnable(String threadName) {
this.threadName = threadName;
}
public void run() {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable: " + threadName + ", i=" + i);
Thread.sleep((int)(Math.random()*100)); // 随机睡眠指定毫秒
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void start() {
if (thread == null) {
thread = new Thread(this, threadName);
thread.start();
}
}
public static void main(String[] args) {
MyTwoRunnable r1 = new MyTwoRunnable("test1");
r1.start();
MyTwoRunnable r2 = new MyTwoRunnable("test2");
r2.start();
}
}
打印效果图:
二)继承Thread类
Thread简介:Thread是一个类。Thread本身就实现了Runnable接口。
public class Thread implements Runnable {
// 代码
}
Thread初始化方式:
方式一:Thread(),分配一个新的 Thread对象,默认。
方式二:Thread(Runnable target),分配一个新的 Thread对象,指定Runnable类型。
方式三:Thread(Runnable target, String name),指定Runnable类型,并指定新线程的名称。
方式四:Thread(String name),分配一个新的 Thread对象,并指定线程的名称。
实现原理:
自定义一个类,继承Thread类,并重写run()方法,通过start()启动线程。
public class MyThread extends Thread {
private String threadName;
public MyThread(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Thread: " + threadName + ", i=" + i);
try {
sleep((int)(Math.random()*100)); // 随机睡眠指定毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 方式一
MyThread t1 = new MyThread("method.1");
MyThread t2 = new MyThread("method.2");
t1.start();
t2.start();
// 方式二: 循环开启几个线程
MyThread thread = null;
for (int i=0; i<3; i++) {
thread = new MyThread("NO."+(i+1));
thread.start();
}
// 方法重复调用,报java.lang.IllegalThreadStateException异常
//t2.start();
}
}
打印效果图:
三)继承Callable接口
Callable<V>简介:
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
实现步骤:
第一步:继承Callable接口,并可以指定任何类型的参数。
第二步:重写实现call()方法。该 call() 方法将作为线程执行体,并且有返回值。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<Object> {
public Object call() throws Exception {
int i = 0;
for (; i < 5; i++) {
System.out.println("Runnable: " + Thread.currentThread().getName() + ", i=" + i);
}
return i;
}
public static void main(String[] args) {
MyCallable myCallable = new MyCallable();
FutureTask<Object> ft1 = new FutureTask<Object>(myCallable);
new Thread(ft1, "有返回值的线程1").start();
FutureTask<Object> ft2 = new FutureTask<Object>(myCallable);
new Thread(ft2, "有返回值的线程2").start();
try {
System.out.println("线程1返回结果为: " + ft1.get());
System.out.println("线程2返回结果为: " + ft2.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
打印效果图:
四)三种多线程实现方式对比
一、采用Runnable和Callable接口创建多线程时,还可以继承其它类,避开了单继承限制。适合多个相同程序代码的线程去处理同一资源。
二、线程池中只能放入实现Runnable或Callable的线程。
三、使用Thread创建多线程时,编写简单。在访问当前线程时,直接用this即可获取线程,无需使用Thread.currentThread()方法。
在java中,每次程序至少会运行2个线程,一个是main线程,一个是垃圾回收线程。
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!