核心概念:
-
线程就是独立的执行路径
-
在程序运行时,即使没有自己创建线程,后台也会有多个线程。如主线程,gc线程
-
main()称之为主线程,为系统的入口,用于执行整个程序
-
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序不能认为干预
-
对同一份资源操作时,会存在资源抢夺的问题,需加入并发控制
-
线程会带来额外的开销,如CPU调度时间,并发控制开销
-
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
线程创建
-
Thread
-
自定义线程类继承Thread类
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
-
-
继承Thread类
-
子类继承Thread类具备多线程能力
-
启动线程:子类对象.start()
-
不建议使用(避免oop单继承局限性)
package com.multithreading.demo01; //创建线程方式一:继承Thread类,重写run()方法,调用start开启线程 //总结:线程开启不一定立即执行,由cpu调度执行 public class TestThread1 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线程,主线程 //创建一个线程对象 TestThread1 testThread1 = new TestThread1(); //调用start方法开启线程 testThread1.start(); for (int i = 0; i < 1000; i++) { System.out.println("我在学习多线程-----"+i); } } }
-
-
实现Runnable接口
-
实现接口Runnable具有多线程能力
-
启动线程:传入目标对象+Thread对象.start()
-
推荐使用(避免单继承局限性,灵活方便,方便同一对象被多个线程使用)
package com.multithreading.demo01; /** * 创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口的实现类 * @author Pan */ public class TestThread3 implements Runnable { @Override public void run() { //run()方法线程体 for (int i = 0; i < 200; i++) { System.out.println("我在看代码-----"+i); } } public static void main(String[] args) { //创建runnable接口的实现类对象 TestThread3 testThread3 = new TestThread3(); //创建线程对象,通过线程对象俩开启线程(代理) // Thread thread = new Thread(testThread3); // // thread.start(); new Thread(testThread3).start(); for (int i = 0; i < 1000; i++) { System.out.println("我在学习多线程-----"+i); } } }
-
-
callable接口
package com.multithreading.demo02; import com.test.TestThread; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; /** * 线程创建方式三:实现callable接口 * callable的好处 * (1)可以定义返回值 * (2)可以抛出异常 * @author Pan */ public class TestCallable implements Callable<Boolean> { private String url; private String name; @Override public Boolean call() { WebDownloader webDownloader = new WebDownloader(); webDownloader.downloader(url,name); System.out.println("成功下载图片:"+name); return true; } public TestCallable(String url, String name) { this.url = url; this.name = name; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1 = new TestCallable("https://ts1.cn.mm.bing.net/th?id=OIP-C.B6pZ8N_dG3MNAYppM-zX0AHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.5&pid=3.1&rm=2","4.jpg"); TestCallable t2 = new TestCallable("https://ts1.cn.mm.bing.net/th?id=OIP-C.B6pZ8N_dG3MNAYppM-zX0AHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.5&pid=3.1&rm=2","5.jpg"); TestCallable t3 = new TestCallable("https://ts1.cn.mm.bing.net/th?id=OIP-C.B6pZ8N_dG3MNAYppM-zX0AHaEo&w=316&h=197&c=8&rs=1&qlt=90&o=6&dpr=1.5&pid=3.1&rm=2","6.jpg"); //创建执行服务 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 = r1.get(); Boolean rs3 = r1.get(); //关闭服务 ser.shutdown(); } } //下载类 class WebDownloader{ 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.multithreading.demo02; /** * 静态代理模式总结: * (1)真实对象和代理对象都要实现同一个接口 * (2)代理对象要代理真实角色 * 好处: * (1)代理对象可以做很多真实对象做不了的东西 * (2)真实对象专注做自己的事情 * @author Pan */ public class StaticProxy { public static void main(String[] args) { /* 理解Thread的静态代理 new Thread(()-> System.out.println("我爱你")).start(); new WeddingCompany(new You()).HappyMarry();*/ // You you = new You();//你要结婚 WeddingCompany weddingCompany = new WeddingCompany(new You()); weddingCompany.HappyMarry(); } } interface Marry{ void HappyMarry(); } //真实角色 class You implements Marry{ @Override public void HappyMarry() { System.out.println("新婚快乐"); } } //代理角色 class WeddingCompany implements Marry{ private Marry target; public WeddingCompany(Marry target) { this.target = target; } @Override public void HappyMarry() { before(); this.target.HappyMarry(); after(); } private void after() { System.out.println("结婚之后收尾款&