一、重写Runnable的run()方法
a.覆写Runnable接口实现多线程可以避免单继承局限
b.当子类实现Runnable接口,此时子类和Thread的代理模式(子类负责真是业务的操作,thread负责资源调度与线程创建辅助真实业务。
在执行过程中start()和run()的区别
start()方法来启动线程,是真正实现的多线程运行,这个时候无需等待run方法体执行完毕,就可以直接执行之后的线程
run() 方法当做普通的方法调用,程序还是要按顺序执行,要等待run()方法体内的数据执行完毕后,才可执行之后的代码
public class MyThread implements Runnable{
public static int count=20;
public void run() {
while(count>0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-当前剩余票数:"+count--);
}
}
public static void main(String[] args) {
MyThread Thread1=new MyThread();
Thread mThread1=new Thread(Thread1,"线程1");
Thread mThread2=new Thread(Thread1,"线程2");
Thread mThread3=new Thread(Thread1,"线程3");
mThread1.start();
mThread2.start();
myThread3.start();
}
}
二、继承Thread类
run()为线程类的核心方法,相当于主线程的main方法,是每个线程的入口
a.一个线程调用 两次start()方法将会抛出线程状态异常,也就是的start()只可以被调用一次
b.native生明的方法只有方法名,没有方法体。是本地方法,不是抽象方法,而是调用c语言方法
registerNative()方法包含了所有与线程相关的操作系统方法
c. run()方法是由jvm创建完本地操作系统级线程后回调的方法,不可以手动调用(否则就是普通方法)
public class MyThread extends Thread {
public MyThread() {
}
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread()+":"+i);
}
}
public static void main(String[] args) {
MyThread mThread1=new MyThread();
MyThread mThread2=new MyThread();
MyThread myThread3=new MyThread();
mThread1.start();
mThread2.start();
myThread3.start();
}
}
继承Thread和实现Runnable接口的区别
a.实现Runnable接口避免多继承局限
b.实现Runnable()可以更好的体现共享的概念
3.覆写Callable接口实现多线程(JDK1.5)
a.核心方法叫call()方法,有返回值
b.有返回值
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyThread implements Callable<String> {
private int count = 20;
@Override
public String call() throws Exception {
for (int i = count; i > 0; i--) {
// Thread.yield();
System.out.println(Thread.currentThread().getName()+"当前票数:" + i);
}
return "sale out";
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<String> callable =new MyThread();
FutureTask <String>futureTask=new FutureTask<>(callable);
Thread mThread=new Thread(futureTask);
Thread mThread2=new Thread(futureTask);
Thread mThread3=new Thread(futureTask);
// mThread.setName("hhh");
mThread.start();
mThread2.start();
mThread3.start();
System.out.println(futureTask.get());
}
}
通过线程池来实现
java的线程池有四种,固定数量的线程池
通过Executor.newFixedThreadPool来创建
核心线程数和最大线程数一样
达到核心线程数后,空闲线程不会超时被终止或释放
每添加一个任务后,会将任务添加到工作任务队列,线程池创建一个线程,线程数等于核心线程数,就不会再创建线程
单线程的线程池
通过Executors.newSingleThreadExecutor来创建
可缓存的线程池
通过NewCachedThreadPool()来创建
核心线程数为0,最大线程数无线大。空闲线程可以缓存60s,空闲超过60s会被回收
使用了SynchronousQueue同步队列,添加任务的同时,要有工作线程来取任务才可以完成任务的添加和执行
定时执行的 线程池
通过Executors.newScheduledThreadPool来创建
可指定核心线程数,最大线程数为无线大,核心线程数空闲不会超过被回收
使用了DelayedWorkQueue延时对垒,可以通过延时队列来控制时间来执行