多线程
线程创建
1.Thread class
继承Thread类,Thread类实现Runnable接口
- (1)自定义线程类继承Thread类
- (2)重写run() 方法,编写线程执行体
- (3)创建线程对象,调用start() 方法启动线程
//线程开始不一定立即执行,要看CPU的调度
//创建线程 继承Thread类 不建议,避免OOP单继承的局限性
public class TestThread extends Thread{
//重写run方法
@Override
public void run() {
//run方法线程体
for (int i=0;i<5;i++){
System.out.println("run"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
for (int i=0;i<6;i++){
System.out.println("main"+i);
}
//创建线程对象
TestThread testThread = new TestThread();
//调用start()方法
testThread.start(); //与主线程同时执行
// testThread.run(); //执行run 不同时
}
}
- 案例:下载图片例子
import java.io.File;
import java.io.IOException;
import java.net.URL;
//Download the pictures
//1.继承Thread
public class TestThread02 extends Thread{
private String url; //网络图片的地址
private String name; //将要保存的文件名
public TestThread02(String url,String name){
this.name=name;
this.url=url;
}
//3.重写run方法
@Override
public void run() {
//下载图片线程的之喜提
WebDownloader webDownloader = new WebDownloader();
webDownloader.download(url,name);
System.out.println("download name:"+name);
}
//主线程main
public static void main(String[] args) {
TestThread02 t1 = new TestThread02("https://hao1.qhimg.com/t01ea3a44e231e5d6f4.png","1.png");
TestThread02 t2 = new TestThread02("https://mvnrepository.com/img/1db2323c3992372f3dc1a4729ff507c5","2.png");
TestThread02 t3 = new TestThread02("https://p1.ssl.qhimg.com/dr/270_500_/t019c311710c700e6dd.jpg?size=800x450","3.png");
t1.start();
t2.start();
t3.start();
}
}
//2.创建下载器
class WebDownloader{
//下载方法
public void download(String url,String name){
try{
//FileUtils工具类 url 网站 file文件名
FileUtils.copyURLToFile(new URL(url),new File(name));
}catch (IOException e){
e.printStackTrace();
System.out.println("downloader方法出现问题");
}
}
}
2.Runnable接口
实现Runnable接口
-
(1)定义一个类实现Runnable接口
-
(2)实现run()方法,编写线程执行体
-
(3)创建线程对象,调用start()方法启动线程
//1.实现Runnable接口 public class TestThread03 implements Runnable{ //2.重写run方法 @Override public void run() { //run方法线程体 for (int i=0;i<5;i++){ System.out.println("run"+i); } } public static void main(String[] args) { //main线程,主线程 for (int i=0;i<6;i++){ System.out.println("main"+i); } //创建Runnable接口实现对象 TestThread03 testThread03 = new TestThread03(); //创建线程对象,通过线程对象来开启线程 代理 Thread thread = new Thread(testThread03); //调用start()方法 thread.start(); //与主线程同时执行 } }
-
案例:抢火车票问题
//多个线程操作同样一个对象 //买火车票例子 //问题:多个线程同时操通一个对象时,线程不安全,数据紊乱 //1.实现Runnable接口 public class TestThread04 implements Runnable{ private int ticketNums=10;//票数 @Override public void run() { while (true){ if (ticketNums<=0){ break; } //Thread.currentThread().getName() 获得当前线程执行的名字 System.out.println(Thread.currentThread().getName()+"拿到了"+ticketNums--+"票"); } } public static void main(String[] args) { TestThread04 testThread04 = new TestThread04(); //创建三个线程 new Thread(testThread04,"你").start(); new Thread(testThread04,"我").start(); new Thread(testThread04,"黄牛").start(); } }
-
案例:模拟龟兔赛跑
//模拟龟兔赛跑 public class Race implements Runnable{ //胜利者 private static String winner; @Override public void run() { for (int i = 0; i <=100 ; i++) { if (Thread.currentThread().getName().equals("rabbit")&&(i+1)%10==0){ //模拟兔子休息 try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } //判断比赛是否结束 boolean flag = gameOver(i); if (flag) break; System.out.println(Thread.currentThread().getName()+"跑了"+i+"步"); } } //判断游戏是否结束 private boolean gameOver(int steps){ if (winner!=null) //已经存在winner return true; else if (steps>=100){ winner=Thread.currentThread().getName(); System.out.println("winner is "+winner); return true; } return false; } public static void main(String[] args) { //多个线程操作同样一个对象 Race race= new Race(); //赛道 new Thread(race,"tortoise").start(); new Thread(race,"rabbit").start(); } }
-
3.Callable接口
实现Callable接口
-
(1)实现Callable接口
-
(2)重写call方法,抛出异常
-
(3)创建目标对象
-
(4)创建执行任务:
-
(5)提交执行任务
-
(6)获取结果
-
(7)关闭服务
import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //1.实现Callable接口 //定义返回值 //抛出异常 public class TestThread05 implements Callable<Boolean> { private String url; //网络图片的地址 private String name; //将要保存的文件名 public TestThread05(String url,String name){ this.name=name; this.url=url; } //2.重写call方法 @Override public Boolean call() throws Exception { WebDownloader webDownloader = new WebDownloader(); webDownloader.download(url,name); System.out.println("download name:"+name); return true; } //主线程main public static void main(String[] args) throws ExecutionException, InterruptedException { TestThread05 t1 = new TestThread05("https://hao1.qhimg.com/t01ea3a44e231e5d6f4.png","1.png"); TestThread05 t2 = new TestThread05("https://mvnrepository.com/img/1db2323c3992372f3dc1a4729ff507c5","2.png"); TestThread05 t3 = new TestThread05("https://p1.ssl.qhimg.com/dr/270_500_/t019c311710c700e6dd.jpg?size=800x450","3.png"); //创建执行服务 ExecutorService ser= Executors.newFixedThreadPool(3); //提交执行 Future<Boolean> r1=ser.submit(t1); Future<Boolean> r2=ser.submit(t2); Future<Boolean> r3=ser.submit(t3); //获取结果 boolean rs1=r1.get(); boolean rs2=r2.get(); boolean rs3=r3.get(); //关闭服务 ser.shutdownNow(); } } //2.创建下载器 class WebDownloader{ //下载方法 public void download(String url,String name){ try{ //FileUtils工具类 url 网站 file文件名 FileUtils.copyURLToFile(new URL(url),new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("downloader方法出现问题"); } } }