多线程_创建多线程
- 进程:一个程序执行起来就是一个进程,一个进程可包含多个线程。
线程创建
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
Thread类(Thread类也始先了runnable接口)
- 继承Thread类。
- 重写run()方法。
- 调用start()方法开启线程。
public class ThreadTest extends Thread{
//重写run方法
@Override
public void run() {
super.run();
for (int i = 0; i < 220; i++) {
System.out.println("RUN"+i);
}
}
public static void main(String[] args) {
ThreadTest t1 = new ThreadTest(); //new一个ThreadTest
ThreadTest t2 = new ThreadTest();
ThreadTest t3 = new ThreadTest();
//调用start()。(调用run()方法就不按照多线程执行了)
t1.start();
t2.start();
t3.start();//三个线程同时执行run()方法内的代码。
for (int i = 0; i < 220; i++) {
System.out.println("main"+i);
}
}
}
实现Runnable接口(推荐,java单继承多实现)
- 定义一个类,实现Runnable接口。
- 实现run()方法。
- new一个Runnable接口的实现类的对象。
- new一个Thread类,将Runnable实现类实例传入形参。
- Thread实现类调用start()方法。
public class ThreadTest implements Runnable{
//实现Runnable接口的run方法
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("run:"+i);
}
}
public static void main(String[] args) {
//实例化接口实现类
ThreadTest threadTest = new ThreadTest();
//实例化RThread类(线程代理)
Thread thread1 = new Thread(threadTest,name);
Thread thread2 = new Thread(threadTest,name);
//启动线程
thread1.start();
thread2.start();
}
}
抢票小demo
public class ThreadTest implements Runnable {
private int P = 20;
@Override
public void run() {
while (true){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (P<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"拿到了第"+P--+"张票子");
}
}
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
new Thread(t,"老师").start();
new Thread(t,"学生").start();
new Thread(t,"黄牛").start();
}
}
输出:
黄牛拿到了第19张票子
老师拿到了第18张票子
学生拿到了第20张票子
学生拿到了第17张票子
老师拿到了第16张票子
黄牛拿到了第15张票子
学生拿到了第13张票子
老师拿到了第14张票子
黄牛拿到了第12张票子
学生拿到了第11张票子
黄牛拿到了第10张票子
老师拿到了第9张票子
黄牛拿到了第8张票子//线程不安全
学生拿到了第8张票子//线程不安全
老师拿到了第8张票子//线程不安全
黄牛拿到了第7张票子
学生拿到了第6张票子
老师拿到了第5张票子
学生拿到了第4张票子
黄牛拿到了第3张票子
老师拿到了第4张票子
老师拿到了第2张票子//线程不安全
学生拿到了第1张票子
黄牛拿到了第2张票子//线程不安全
- Thread类的currentThread()方法可拿到线程的名字等信息。
- Thread.sleep(200)可以让线程延迟启动。
- 线程不安全!数据被重复使用了!
龟兔赛跑小demo
public class ThreadTest implements Runnable {
private static String win; //胜者,static只执行一次
@Override
public void run() {
for (int i = 0; i <= 100; i++) { //跑100步
if (Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(1); //兔子每10米睡一觉
} catch (InterruptedException e) {
e.printStackTrace();
}
}
boolean b = gameOver(i);
if (b){ //判断比赛是否结束
break;
}else { //记录步数
System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
}
}
}
//判断比赛是否结束的方法
public boolean gameOver(int i){
if (win!=null){ //产生胜利者
return true;
}else if (i==100){ //先到达100的
win = Thread.currentThread().getName(); //赋值给win
System.out.println(Thread.currentThread().getName()+"win");
return true;
}
return false; //还没分出胜负
}
public static void main(String[] args) {
ThreadTest threadTest = new ThreadTest();
new Thread(threadTest,"乌龟").start();
new Thread(threadTest,"兔子").start();
}
}
实现Callable接口
- 重写Callable接口(带泛型)。
- 重写call方法(有返回值,和泛型相同)。
- new一个Callable方法的实现类。
- 创建执行任务。
- 提交执行。
- 获取结果。
- 关闭服务。
import java.util.concurrent.*;
public class ThreadTest implements Callable<String> {
String s;
//重写call方法
@Override
public String call(){
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+"的i等于:"+i);
s=Thread.currentThread().getName();
}
return s;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//new Callable 接口的实现类
ThreadTest t1 = new ThreadTest();
ThreadTest t2 = new ThreadTest();
ThreadTest t3 = new ThreadTest();
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
//submit提交执行
Future<String> submit1 = executorService.submit(t1);
Future<String> submit2 = executorService.submit(t2);
Future<String> submit3 = executorService.submit(t3);
//获取结果
String aBoolean1 = submit1.get();
String aBoolean2 = submit2.get();
String aBoolean3 = submit3.get();
System.out.println(aBoolean1);
System.out.println(aBoolean2);
System.out.println(aBoolean3);
//关闭服务
executorService.shutdown();
}
}