目录
方式一:通过继承Thread类的方式
步骤:
1.创建类继承Thread类
2.重写Thread类中的run()方法
3.创建子类的实例对象
4.调用子类实例对象的start()方法
例:创建一个线程实现输出0~100
package test1;
//创建继承Thread类的子类
public class ThreadTest1 extends Thread{
//重写该子类的run()方法
public void run() {
for(int i=1;i<=100;i++) {
System.out.println("数"+i);
}
}
}
package test1;
public class ThreadTest {
//主线程
public static void main(String []args) {
//创建子类的实例化对象
ThreadTest1 threadTest1=new ThreadTest1();
//调用子类实例化对象的start()方法
threadTest1.start();
}
}
方式二:通过实现Runnable接口的方式
步骤:
1.创建Runnable接口的实现类
2.重写该实现类的run()方法
3.创建该实现类的实例化对象
4.以该实例化对象为参数创建Thread类的实例化对象
5.调用Thread类的实例化对象的start()方法
例:创建一个线程实现输出0~100
package test1;
//创建实现Runnabl接口的子类
public class ThreadTest1 implements Runnable{
//重写该实现类的run()方法
public void run() {
for(int i=1;i<=100;i++) {
System.out.println("数"+i);
}
}
}
package test1;
public class ThreadTest {
//主线程
public static void main(String []args) {
//创建实现类的实例化对象
ThreadTest1 threadTest1=new ThreadTest1();
//以实现类的实例化对象为参数创建Thread类的实例化对象
Thread theadThread=new Thread(threadTest1);
//调用Thread类的实例化对象的start()方法
theadThread.start();
}
}
方式三:通过实现Callable接口的方式
步骤:
1.创建实现Callable接口的实现类
2.重写该实现类的call方法
3.创建该实现类的实例化对象
4.以Callable实现类的实例化对象为参数创建FutureTask类的实例化对象
5.以FutureTask类的实例化对象为参数创建Thread类的实例化对象
6.调用Thread类的实例化对象的start()方法
7.call方法有返回值,如果需要获取返回值则调用FutureTask类的实例化对象的get()方法
例:创建一个线程实现输出0~100,并返回1到100之和
package test1;
import java.util.concurrent.Callable;
//创建实现Callable接口的子类
public class ThreadTest1 implements Callable{
//重写该实现类的call()方法
@Override
public Object call() throws Exception {
Integer sum=0;
for (int i=1;i<=100;i++) {
System.out.println("数"+i);
sum+=i;
}
return sum;
}
}
package test1;
import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;
public class ThreadTest {
//主线程
public static void main(String []args) {
//创建实现类的实例化对象
ThreadTest1 threadTest1=new ThreadTest1();
//以实现类的实例化对象为参数创建FutureTask类的实例化对象
FutureTask futureTask=new FutureTask(threadTest1);
//以FutureTask类的实例化对象为参数创建Thread类的实例化对象
Thread theadThread=new Thread(futureTask);
//调用Thread类的实例化对象的start()方法
theadThread.start();
//调用FutureTask类的实例化对象的get()方法
try {
Integer sumInteger=(Integer) futureTask.get();
int sum=sumInteger;
System.out.println(sum);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
方式四:通过线程池的方式
步骤:
1.创建线程池
2.创建Thread类或实现了Runnable或者Callable的类(重写了run()/call()方法)的实例化对象
3.调用线程池中的某个线程执行任务
4.关闭线程池
例:通过线程池使用一个线程输出1-100的整数
package test1;
import java.util.concurrent.Callable;
//创建实现Callable接口的子类
public class ThreadTest1 implements Callable{
//重写该实现类的call()方法
@Override
public Object call() throws Exception {
Integer sum=0;
for (int i=1;i<=100;i++) {
System.out.println("数"+i);
sum+=i;
}
return sum;
}
}
package test1;
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;
public class ThreadTest {
//主线程
public static void main(String []args) {
//创建有10个线程的线程池
ExecutorService executorService=Executors.newFixedThreadPool(10);
/*上行代码中ExecutorService为真正的线程池接口,Executors是线程池工具类
* newFixedThreadPool(int n)是Executors工具类的一个静态方法,用来获取
* 具有n个线程的线程池
*/
//创建实现了Callable接口的实现类的实例化对象
ThreadTest1 test1=new ThreadTest1();
//调用线程池中的某个线程执行任务
Future sum=executorService.submit(test1);
/*如果是Thread的子类或者是实现了Runnable接口的类使用void execute(Runnable command) 方法
*/
//关闭线程池
executorService.shutdown();
}
}
对于start()方法的解释
start()有两个作用:
1.启动一个线程
2.调用该线程的run()方法
对于run()方法的解释:
通过上面的创建多线程示例,我们发现如果是实现Runnable和Callable接口的方式,我们的线程执行的代码(也就是重写的run()和call())并不是我们通过具体实现类来调用的,而是通过一个Thread类的实例化对象调用start()后系统调用的。这是因为我们通过Thread类的实例化对象调用start()后其会调用run()而Thread的run()的源码如下:
/* What will be run. */
private Runnable target;
------
@Override
public void run() {
if (target != null) {
target.run();
}
}
也就是说,如果Thread类的对象在示例化时参数传入了一个实现Runnable接口的对象,则会调用参数对象的run()方法,所以能调用我们实现类的run()和call()。