Java 中创建线程主要有三种方式:
一, 继承 Thread 类创建线程类
(1) 定义 Thread 类的子类, 并重写该类的 run 方法, 该 run 方法的方法体就代表了线程要完成的任务. 因此把 run() 方法称为执行体.
(2) 创建 Thread 子类的实例, 即创建了线程对象.
(3) 调用线程对象的 start() 方法来启动该线程.
- package com.nf147.Constroller;
- public class FirstThreadTest extends Thread {
- int i = 0;
- // 重写 run 方法, run 方法的方法体就是现场执行体
- public void run() {
- for (; i <100; i++) {
- System.out.println(getName() + " " + i);
- }
- }
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + ":" + i);
- if (i == 50) {
- new FirstThreadTest().start();
- new FirstThreadTest().start();
- }
- }
- }
- }
上述代码中 Thread.currentThread() 方法返回当前正在执行的线程对象. GetName() 方法返回调用该方法的线程的名字.
二, 通过 Runnable 接口创建线程类
(1) 定义 runnable 接口的实现类, 并重写该接口的 run() 方法, 该 run() 方法的方法体同样是该线程的线程执行体.
(2) 创建 Runnable 实现类的实例, 并依此实例作为 Thread 的 target 来创建 Thread 对象, 该 Thread 对象才是真正的线程对象.
(3) 调用线程对象的 start() 方法来启动该线程.
- package com.nf147.Constroller;
- public class RunnableThreadTest implements Runnable{
- private int i;
- public void run()
- {
- for(i = 0;i <100;i++)
- {
- System.out.println(Thread.currentThread().getName()+" "+i);
- }
- }
- public static void main(String[] args)
- {
- for(int i = 0;i < 100;i++)
- {
- System.out.println(Thread.currentThread().getName()+" "+i);
- if(i==20)
- {
- RunnableThreadTest rtt = new RunnableThreadTest();
- new Thread(rtt,"新线程 1").start();
- new Thread(rtt,"新线程 2").start();
- }
- }
- }
- }
三, 通过 Callable 和 Future 创建线程
(1) 创建 Callable 接口的实现类, 并实现 call() 方法, 该 call() 方法将作为线程执行体, 并且有返回值.
(2) 创建 Callable 实现类的实例, 使用 FutureTask 类来包装 Callable 对象, 该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值.
(3) 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程.
(4) 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值
实例代码:
- package com.nf147.Constroller;
- import java.util.concurrent.Callable;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.FutureTask;
- public class CallableThreadTest implements Callable<Integer> {
- public static void main(String[] args) {
- CallableThreadTest ctt = new CallableThreadTest();
- FutureTask<Integer> ft = new FutureTask<>(ctt);
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + "的循环变量 i 的值" + i);
- if (i == 20) {
- new Thread(ft, "有返回值的线程").start();
- }
- }
- try {
- System.out.println("子线程的返回值:" + ft.get());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- @Override
- public Integer call() throws Exception {
- int i = 0;
- for (; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + " " + i);
- }
- return i;
- }
- }
二, 创建线程的三种方式的对比
采用实现 Runnable,Callable 接口的方式创见多线程时, 优势是:
线程类只是实现了 Runnable 接口或 Callable 接口, 还可以继承其他类.
在这种方式下, 多个线程可以共享同一个 target 对象, 所以非常适合多个相同线程来处理同一份资源的情况, 从而可以将 CPU, 代码和数据分开, 形成清晰的模型, 较好地体现了面向对象的思想.
劣势是:
编程稍微复杂, 如果要访问当前线程, 则必须使用 Thread.currentThread() 方法.
使用继承 Thread 类的方式创建多线程时优势是:
编写简单, 如果需要访问当前线程, 则无需使用 Thread.currentThread() 方法, 直接使用 this 即可获得当前线程.
劣势是:
线程类已经继承了 Thread 类, 所以不能再继承其他父类.
- package com.nf147.Constroller;
- public class FirstThreadTest extends Thread {
- int i = 0;
- // 重写 run 方法, run 方法的方法体就是现场执行体
- public void run() {
- for (; i < 100; i++) {
- System.out.println(getName() + " " + i);
- }
- }
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- System.out.println(Thread.currentThread().getName() + ":" + i);
- if (i == 50) {
- new FirstThreadTest().start();
- new FirstThreadTest().start();
- }
- }
- }
- }
来源: http://www.bubuko.com/infodetail-2984184.html