Java多线程
程序
程序是指令和数据的有序集合,是一个静态的概念
进程(process)
进程是程序的一次执行过程,是动态的概念,是系统资源分配的单位
线程(Thread)
通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,线程是CPU调度和执行的单位
线程三种创建方式
继承Thread类
package com.henry.thread; //继承Thread类,重写run方法,调用start开启线程 public class TestThread extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("x+"+i); } } public static void main(String[] args) { //创建一个线程对象 TestThread testThread = new TestThread(); //调用start方法开启线程 testThread.start(); //main线程,主线程 for (int i = 0; i < 1000 ; i++) { System.out.println("y+"+i); } } }
多线程下载图片
package com.henry.thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; public class TestThread2 extends Thread{ private String url; private String filename; public TestThread2(String url, String filename) { this.url = url; this.filename = filename; } @Override public void run() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,filename); System.out.println("下载了文件名为:"+filename); } public static void main(String[] args) { TestThread2 t1 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829165338623-1016877944.png","1.png"); TestThread2 t2 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829170405010-1982825617.png","2.png"); TestThread2 t3 = new TestThread2("https://pic.cnblogs.com/avatar/2035046/20200511235307.png","3.png"); t1.start(); t2.start(); t3.start(); //下载了文件名为:2.png //下载了文件名为:1.png //下载了文件名为:3.png } } class WebDownloader{ public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
实现Runnable接口
package com.henry.thread; //创建线程方式2:实现runnable接口,重写run方法,执行线程需要runnable接口实现类 public class TestThread3 implements Runnable{ public void run() { for (int i = 0; i < 10; i++) { System.out.println("x+"+i); } } public static void main(String[] args) { //创建runnable接口的实现类对象 TestThread3 testThread3 = new TestThread3(); //创建线程对象,通过线程对象开启我们的线程 new Thread(testThread3).start(); for (int i = 0; i < 1000 ; i++) { System.out.println("y+"+i); } } }
多线程下载图片
package com.henry.thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; public class TestThread2 implements Runnable{ private String url; private String filename; public TestThread2(String url, String filename) { this.url = url; this.filename = filename; } public void run() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,filename); System.out.println("下载了文件名为:"+filename); } public static void main(String[] args) { TestThread2 t1 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829165338623-1016877944.png","1.png"); TestThread2 t2 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829170405010-1982825617.png","2.png"); TestThread2 t3 = new TestThread2("https://pic.cnblogs.com/avatar/2035046/20200511235307.png","3.png"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); //下载了文件名为:2.png //下载了文件名为:1.png //下载了文件名为:3.png } } class WebDownloader{ public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
实现Callable接口
package com.henry.thread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; public class TestThread2 implements Callable<Boolean> { private String url; private String filename; public TestThread2(String url, String filename) { this.url = url; this.filename = filename; } public Boolean call() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,filename); System.out.println("下载了文件名为:"+filename); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestThread2 t1 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829165338623-1016877944.png","1.png"); TestThread2 t2 = new TestThread2("https://img2020.cnblogs.com/blog/2035046/202008/2035046-20200829170405010-1982825617.png","2.png"); TestThread2 t3 = new TestThread2("https://pic.cnblogs.com/avatar/2035046/20200511235307.png","3.png"); //创建执行服务 ExecutorService service = Executors.newFixedThreadPool(3); //提交执行 Future<Boolean> r1 = service.submit(t1); Future<Boolean> r2 = service.submit(t2); Future<Boolean> r3 = service.submit(t3); //获取结果 Boolean rb1 = r1.get(); Boolean rb2 = r2.get(); Boolean rb3 = r3.get(); //关闭服务 service.shutdownNow(); } } class WebDownloader{ public void downloader(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { e.printStackTrace(); } } }
龟兔赛跑问题
package com.henry.thread; public class Race implements Runnable{ private String winner; 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+"步"); } } private boolean gameOver(int steps){ if(winner != null){ 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,"兔子").start(); new Thread(race,"乌龟").start(); } }
并发问题
package com.henry.thread; public class TestThread4 implements Runnable{ private int ticketNum =10; public void run() { while(true){ if(ticketNum<=0){ break; } try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿到了第"+ticketNum--+"票"); } } public static void main(String[] args) { TestThread4 testThread4 = new TestThread4(); new Thread(testThread4,"记得").start(); new Thread(testThread4,"单独").start(); new Thread(testThread4,"安安").start(); //多个线程操作同一个资源,线程不安全,数据紊乱 } }