多线程的调动是随着cpu调度的,可以给线程设置优先级,但最终还是要依靠CPU的调度,无法确定线程的执行顺序。
多线程的实现方法
继承Thread类,重写run()方法,调用start开始线程;
实现Runnable接口,重写run()方法,执行线程需要丢入Runnable实现接口类,调用start方法;
实现Callable接口,并用其初始化Thread,然后创建Thread实例,并调用start方法。
详细说明
继承Thread类
//创建线程方式一:继承Thread类,重写run()方法,调用start开始线程
public class demo1 extends Thread {
@Override
public void run() { //重写run方法
for (int i = 0; i <= 99; i++) {
System.out.println(i+"在学习多线程");
}
}
public static void main(String[] args) {
demo1 thread = new demo1();
thread.start(); //启动run方法
for (int i = 0; i <= 99; i++) {
System.out.println("主方法"+i+"也在学习多线程");
}
}
}
Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,启动线程的唯一方法就是通过Thread类的start()实例方法。执行结果是随着cpu调度的,可以给线程设置优先级,但最终还是要依靠CPU的调度,无法确定线程的执行顺序。
实现Runnable接口
public class demo4 implements Runnable {
private int ticketNum = 10;
@Override
public void run() { //重写run方法
while (true){
if (ticketNum<=0){
break;
}
System.out.println(Thread.currentThread().getName() + "拿走了第"+ ticketNum + "票。");
ticketNum--;
}
}
public static void main(String[] args) {
demo4 t1 = new demo4();
demo4 t2 = new demo4();
demo4 t3 = new demo4();
new Thread(t1,"Jeri").start(); //执行线程
new Thread(t2,"Jordon").start();
new Thread(t3,"Knight").start();
}
}
当自己的类已经继承(extends)了另一个类,就无法再次extends Thread。此时,必须实现一个Runnable接口,如上所示。但实现Runnable接口的线程执行与extends Thread有所不同,需要new一个Thread对象,再把线程丢入,最后start.
举一个龟兔赛跑的例子,乌龟不停跑,兔子偶尔会休息:
//龟兔赛跑模拟
public class demo5_race implements Runnable {
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//如果是兔子,就让他休息1ms,下面的条件表示的是i是10的倍数时兔子再休息
if (Thread.currentThread().getName().equals("兔子") && i % 10 ==0){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断是否有胜利者出现了
boolean flag = gameOver(i);
if (flag){
break;
}
System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
}
}
//判断比赛是否结束了
public boolean gameOver(int step){
if (winner != null){
return true;
}{
if (step >= 100){
winner = Thread.currentThread().getName();
System.out.println(winner + " is winner!");
return true;
}
}
return false;
}
//主函,两个线程
public static void main(String[] args) {
demo5_race race = new demo5_race();
new Thread(race,"乌龟").start();
new Thread(race,"兔子").start();
}
}
当使用Thread.sleep()方法时,就模拟了兔子的休息。此时乌龟仍然在跑。运行结果自然就大概率是乌龟是赢家。
实现Callable接口
package thread;
import java.util.concurrent.*;
public class demo6_callable implements Callable {
@Override
public Boolean call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"call方法的线程正在跑...");
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"主方法的线程...");
}
demo6_callable demo6 = new demo6_callable();
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future sub = ser.submit(demo6);
//获取结果
Boolean aBoolean = sub.get();
//关闭服务
ser.shutdown();
}
}