创建线程的四种方法
创建线程有四种方法:继承Thread,实现Runnable接口,实现Callable接口,线程池
- 继承Thread
实现Thread的run方法,调用start()方法启动线程
(1)创建一个继承于Thread类的子类
(2)重写run方法,将此线程继承的操作写在run方法中
(3)创建Thread类的子类的对象
(4)调用start方法启动线程,线程处于就绪状态
public class MyThreadTest {
public static void main(String[] args) {
Number number1=new Number();
Number number2=new Number();
number1.start();
number2.start();
}
}
class Number extends Thread{
private static int num=0;
@Override
public void run() {
while(true){
if(num<100){
System.out.println(getName()+" 输出数字 "+num);
num++;
}else {
break;
}
}
}
}
- 实现Runnable接口
(1)创建一个实现Runnable接口的类
(2)实现类实现run方法
(3)创建实现类的对象
(4)创建Thread类的对象,构造器为该实现类
(5)调用start方法
public class RunnaleTest {
public static void main(String[] args) {
Number2 number1=new Number2();
Thread t1=new Thread(number1);
Thread t2=new Thread(number1);
t1.start();
t2.start();
}
}
class Number2 implements Runnable{
private static int num=0;
@Override
public void run() {
while(num<100){
System.out.println(Thread.currentThread().getName()+" 输出数字 "+num);
num++;
}
}
}
- JDK5.0 实现Callable接口
run方法可以有返回值
方法可以抛出异常
支持泛型的返回值
需要借助FutureTask类,比如获取返回结果
Future接口:
(1)可以对具体Runnable,Callable任务的执行结果进行取消、查询是否完成、获取结果等
(2)FutureTask是Future接口的唯一实现类
(3)FutureTask同时实现了Runnable,Future接口,它既可以作为Runnable被线程执行,又剋以作为Future得到Callable的返回值
/**
* 通过实现Callable接口来创建线程
*/
public class ThreadNew {
public static void main(String[] args) {
//3.创建Callable实现类的对象
NumThred numThred=new NumThred();
//4.将此Callable接口实现类的对象传入到FutureTask构造器中,创建FutureTask对象
FutureTask futureTask=new FutureTask(numThred);
//5.将FutureTask的对象作为参数传入到Thread的构造器中,创建Thread对象,并调用start方法
Thread thread=new Thread(futureTask);
thread.start();
try {
//6.使用get()方法获取call方法中的返回值
Object object=futureTask.get();
System.out.println("总和为 "+object);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
//1.创建一个实现Callablede 实现类
class NumThred implements Callable{
private static int sum=0;
//2.实现call方法,将此线程需要执行的操作声明在call中
@Override
public Object call() throws Exception {
for(int i=0;i<=100;i++){
if(i%2==0){
System.out.println(i);
sum+=i;
}
}
return sum;
}
}
- 使用线程池 JDK5.0
提前创建好多个线程,放入线程池中,使用时直接获取,使用完成放回池中,可以避免频繁创建销毁,实现重复利用。
/**
* 使用线程池创建线程
*/
public class ThreadPool {
public static void main(String[] args) {
//提供指定线程数量的线程池
ExecutorService service= Executors.newFixedThreadPool(10);
//2.执行指定的线程操作,需要提供实现Ruannable或者Callable实现类的对象
service.execute(new NumberThread());//适用于Runnable
service.execute(new NumberThread1());
// service.submit();//适用于Callable
//3.关闭连接
service.shutdown();
}
}
class NumberThread implements Runnable {
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
}
class NumberThread1 implements Runnable{
@Override
public void run() {
for(int i=1;i<=100;i++){
if(i%2==1){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
}
线程的生命周期
- 新建
new创建一个线程 - 就绪
调用了start()方法,此时cpu还没给线程分配资源 - 运行
- 阻塞
- 死亡
线程安全问题
在java中,通过同步机制,来解决线程的安全问题
有三种同步方法