线程创建
三种创建方式:①Thread class 继承Thread类
②Runnable接口 实现(implement)Runnable接口,Thread类就是实现了Runnable接口
③Callable接口 实现Callable接口
Thread类
自定义线程类继承Thread类;重写run方法,编写程序执行体;创建线程对象,调用start方法启动线程。
package com.wang.thread;//创建线程方式一:继承Thread类,重写run方法,调用start方法开启线程public class ThreadDemo01 extends Thread{ @Override public void run(){ //run方法线程体 for (int i = 0; i < 200; i++) { System.out.println("我在"+i); } } public static void main(String[] args) { //main线程,主线程 //创建一个线程对象 ThreadDemo01 threadDemo01=new ThreadDemo01(); //调用start方法开启线程 threadDemo01.start(); //两条线程同时执行,交替执行 for (int i = 0; i < 2000; i++) { System.out.println("我在学习多线程"+i); } }}
线程开启不一定立即执行,由cpu调度执行
案例:用多线程同时下载几个图片
分析:下载图片首先需要一个下载器,所以先写一个下载器,在下载器中写下载方法,通过FileUtils工具类的方法copyURLToFile,把URL变成一个文件,参数需要一个url和name。
实现线程类,继承Thread类,变成线程类,在类中重写run方法,run方法就是线程的执行体。
创建三个线程,通过start将三个线程同时启
package com.practice.thread;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;//common.io是别人写好的,直接下载下来用//练习thread,实现多线程同步下载图片public class ThreadDemo01 extends Thread { private String url;//网络图片地址 private String name;//保存的文件名 public ThreadDemo01(String url,String name){ this.url=url; this.name=name; } @Override public void run() {//下载图片线程的执行体 WebDownloader webDownloader=new WebDownloader(); webDownloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { ThreadDemo01 t1=new ThreadDemo01("http://pic.ruiwen.com/allimg/1708/598c8d3752d8939511.jpg?x-oss-process=style/qr.ruiwen","2.jpg"); ThreadDemo01 t2=new ThreadDemo01("http://pic.ruiwen.com/allimg/1708/598c8d37c8e9a56734.jpg?x-oss-process=style/qr.ruiwen","3.jpg"); ThreadDemo01 t3=new ThreadDemo01("https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike150%2C5%2C5%2C150%2C50/sign=e90c38903ea85edfee81f671283d6246/3ac79f3df8dcd100ef9ca9e1788b4710b8122fe9.jpg","YIBO.jpg"); t1.start(); t2.start(); t3.start(); }}//下载器class WebDownloader{ //下载方法 public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name));//FileUtil文件工具包,copyURLToFile把网页地址变成一个文件 }catch(IOException e){ e.printStackTrace(); System.out.println("IO异常,downloader方法出现问题"); } }}
实现Runnable
定义MyRunnable类实现Runnable接口;重写run方法,编写线程执行体;创建线程对象,调用start方法启动线程。
package com.wang.thread;//创建线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口的实现类,调用startpublic class RunnableDemo01 implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("我在"+i); } } public static void main(String[] args) { //创建Runnable接口的实现类的对象 RunnableDemo01 runnableDemo01=new RunnableDemo01(); //创建线程对象,通过线程对象来开启我们的线程,代理 //Thread thread=new Thread(runnableDemo01); //thread.start(); new Thread(runnableDemo01).start(); for (int i = 0; i < 1000; i++) { System.out.println("我在学习多线程"+i); } }}
案例:用多线程同时下载几个图片
package com.practice.thread;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;public class RunnableDemo01 implements Runnable { private String url; private String name; public RunnableDemo01(String url,String name){ this.url=url; this.name=name; } @Override public void run() { WebDownloader downloader=new WebDownloader(); downloader.downloader(url,name); System.out.println("下载了文件名为:"+name); } public static void main(String[] args) { RunnableDemo01 r1=new RunnableDemo01("http://pic.ruiwen.com/allimg/1708/598c8d3752d8939511.jpg?x-oss-process=style/qr.ruiwen","2.jpg"); RunnableDemo01 r2=new RunnableDemo01("http://pic.ruiwen.com/allimg/1708/598c8d37c8e9a56734.jpg?x-oss-process=style/qr.ruiwen","3.jpg"); RunnableDemo01 r3=new RunnableDemo01("https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike150%2C5%2C5%2C150%2C50/sign=e90c38903ea85edfee81f671283d6246/3ac79f3df8dcd100ef9ca9e1788b4710b8122fe9.jpg","YIBO.jpg"); new Thread(r1).start(); new Thread(r2).start(); new Thread(r3).start(); }}class WebDownloader1{ public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url), new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("IO异常,downloader方法出现异常"); } }}
实现Runnable接口,能避免单继承局限性,灵活方便,方面同一个对象被多个线程使用
多个线程操作同一个资源的情况下,线程不安全,数据紊乱,并发
package com.wang.thread;//多个线程同时操作同一个对象//买火车票的例子//多个线程操作同一个资源的情况下,线程不安全,数据紊乱public class RunnableDemo02 implements Runnable { //票数 private int ticketNumbers=10; @Override public void run() { while (true){ if (ticketNumbers<=0){ break; } try { Thread.sleep(200);//模拟延时 延迟0.2秒 } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().getName()当前执行线程的名字 System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNumbers--+"张票"); } } public static void main(String[] args) { RunnableDemo02 r=new RunnableDemo02(); new Thread(r,"小明").start(); new Thread(r,"老师").start(); new Thread(r,"王迎婧").start(); }}
案例:龟兔赛跑-Race
package com.practice.thread;public class RaceDemo implements Runnable { //胜利者 private static String winner; @Override public void run() { for (int i = 0; i <=100; i++) { //模拟兔子休息 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 steps){ //判断是否有胜利者 if (winner!=null){//已经存在胜利者 return true; }{ if (steps>=100){ winner=Thread.currentThread().getName(); System.out.println("winner is "+winner); return true; } } return false; } public static void main(String[] args) { RaceDemo raceDemo=new RaceDemo();//赛道只有一条 new Thread(raceDemo,"兔子").start(); new Thread(raceDemo,"乌龟").start(); }}
实现Callable接口
1、实现Callable接口,需要返回值类型
2、重写call方法,需要抛出异常
3、创建目标对象
4、创建执行服务:ExecutorService ser=Executors.newFixedThreadPool(1);
5、提交执行:Future<Boolean> result1=ser.submit(t1);
6、获取结果:boolean r1=result1.get();
7、关闭服务:ser.shutdownNow();
Callable的好处:可以定义返回值;可以抛出异常
package com.practice.thread;import com.wang.duixiang.B;import org.apache.commons.io.FileUtils;import java.io.File;import java.io.IOException;import java.net.URL;import java.util.concurrent.*;/** * 线程创建方式三:实现Callable接口 * 1、实现Callable接口,需要返回值类型 * 2、重写call方法,需要抛出异常 * 3、创建目标对象 * 4、创建执行服务:ExecutorService ser=Executors.newFixedThreadPool(1); * 5、提交执行:Future <Boolean> result1=ser.submit(t1); * 6、获取结果:boolean r1=result1.get(); * 7、关闭服务:ser.shutdownNow(); */public class CallableDemo01 implements Callable<Boolean> { private String url; private String name; public CallableDemo01(String url,String name){ this.url=url; this.name=name; } @Override public Boolean call() { WebDownloader2 downloader=new WebDownloader2(); downloader.downloader(url,name); System.out.println("下载了文件名为:"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { CallableDemo01 c1=new CallableDemo01("http://pic.ruiwen.com/allimg/1708/598c8d3752d8939511.jpg?x-oss-process=style/qr.ruiwen","2.jpg"); CallableDemo01 c2=new CallableDemo01("http://pic.ruiwen.com/allimg/1708/598c8d37c8e9a56734.jpg?x-oss-process=style/qr.ruiwen","3.jpg"); CallableDemo01 c3=new CallableDemo01("https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/c0%3Dbaike150%2C5%2C5%2C150%2C50/sign=e90c38903ea85edfee81f671283d6246/3ac79f3df8dcd100ef9ca9e1788b4710b8122fe9.jpg","YIBO.jpg"); //创建执行服务:ExecutorService ser=Executors.newFixedThreadPool(1); ExecutorService ser= Executors.newFixedThreadPool(3); //提交执行:Future <Boolean> result1=ser.submit(t1); Future<Boolean> result1=ser.submit(c1); Future<Boolean> result2=ser.submit(c2); Future<Boolean> result3=ser.submit(c3); //获取结果:boolean r1=result1.get(); boolean r1=result1.get(); boolean r2=result2.get(); boolean r3=result3.get(); //关闭服务 ser.shutdownNow(); }}class WebDownloader2{ public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url), new File(name)); }catch (IOException e){ e.printStackTrace(); System.out.println("IO异常,downloader方法出现异常"); } }
package com.wang.thread;import java.util.concurrent.*;//回顾总结线程的创建public class TestThread { public static void main(String[] args) throws ExecutionException, InterruptedException { new MyThread1().start(); new Thread(new MyThread2()).start(); MyThread3 myThread3=new MyThread3(); ExecutorService service= Executors.newFixedThreadPool(1); Future<Integer> result=service.submit(myThread3); Integer integer=result.get(); System.out.println(integer); service.shutdownNow(); }}//1、继承Thread类class MyThread1 extends Thread{ @Override public void run() { System.out.println("MyThread1"); }}//2、实现Runnable接口class MyThread2 implements Runnable{ @Override public void run() { System.out.println("MyThread2"); }}//3、实现Callable接口class MyThread3 implements Callable<Integer>{ @Override public Integer call() throws Exception { System.out.println("MyThread3"); return 100; }}