多线程一直给大家一种很难的感觉,其实接触了解之后你会发现,没有大家想的那么深奥,接下来我会分享我学习多线程的经历给大家,下面先简单的介绍下实现线程的三种方式:
1、继承Thread
(1)定义Thread类的子类,并重写该类的run方法,该方法的方法体就代表了线程需要完成的任务。可以把run方法称为线程执行体。
(2)创建Thread子类的实例,即创建了线程对象。
(3)调用线程对象的start方法来启动线程。
package com.xiaomo.thread;
public class ExtendThread extends Thread {
private int i;
public void run() {
// 当线程继承Thread类时,直接使用this即可获取当前线程
// Thread对象的getName()返回当前线程的名字
// 因此可以直接调用getName()方法返回当前线程的名字
for (; i < 100; i++) {
System.out.println(this.getName() + " " + i);
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
// 调用Thread的currentThread()方法获取当前线程
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
// 创建并启动第一个线程
new ExtendThread().start();
// 创建并启动第二个线程
new ExtendThread().start();
}
}
}
}
结果:
main 0
main 1
。
。
main 19
main 20
Thread-0 0
Thread-0 1
。
。
Thread-0 21
Thread-0 22
。
。
Thread-1 98
Thread-1 99
继承Thread类的实现类不共享实例属性。
2、实现Runnable
(1)定义Runnable接口的实现类,并重写该接口的run方法,该方法的方法体就是该线程的线程执行体。
(2)创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
(3)调用线程对象的start方法来启动该线程。
package com.xiaomo.thread;
public class ImplRunnable implements Runnable {
private int i;
public static void main(String[] args) {
for (int i = 0; i < 100; i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i == 20){
ImplRunnable ir = new ImplRunnable();
new Thread(ir,"线程一").start();
new Thread(ir,"线程二").start();
}
}
}
@Override
public void run() {
for (; i < 100; i++) {
// 当线程实现Runnable接口时
// 如果想获得当前线程,只能用Thread.currentThread()方法
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
结果:
main 0
main 1
main 2
。
。
。
main 19
main 20
线程一 0
线程一 1
。
。
。
线程一 70
线程二 72
main 46
线程二 74
线程一 73
线程二 75
。
。
。
线程一 79
main 98
main 99
实现Runnable类的实现类共享实例属性。
3、使用Callable和Future创建线程
(1)创建Callable接口的实现类,并实现cal方法,该call方法将作为线程执行体,且该call方法有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get方法来获取子线程执行结束后的返回值。
package com.xiaomo.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ImplCallable implements Callable<Integer> {
public static void main(String[] args) {
//创建Callable对象
ImplCallable ic = new ImplCallable();
//使用FutureTask<Integer>来包装Callable对象
FutureTask<Integer> task = new FutureTask<>(ic);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
if(i == 20){
//实质还是以Callable对象来创建并启动线程
new Thread(task, "有返回值的线程").start();
}
}
try{
//获取线程返回值
System.out.println("子线程的返回值:"+task.get());
}catch(Exception ex){
ex.printStackTrace();
}
}
//实现call()方法,作为线程执行体
@Override
public Integer call() throws Exception {
int i = 0;
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
//call方法可以有返回值
return i;
}
}
结果:
main 0
main 1
。
。
main 33
有返回值的线程 0
有返回值的线程 1
有返回值的线程 2
。
。
有返回值的线程 98
有返回值的线程 99
main 34
。
。
main 99
子线程的返回值:100
该方式可以获取返回值。