- 线程简介
- 线程创建
- 继承Thread类
- 网图下载 (案例)
- 实现Runnable接口
- 下载图片案例
- 并发线程
- 实现Callable接口
- 静态代理
任务,进程,线程,多线程
一个个体一起做多个事情叫多任务,
Process 进程 (执行程序的一次执行过程,是动态,系统分配的单位)
Thread 线程 (一个进程包含若干线程,一个进程至少有一个线程,否则没存在意义,线程是CPU调度的执行的单位)
注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错局。
–线程是独立的执行路径
线程创建 继承Thread类◆线程就是独立的执行路径;
◆在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,g线程
◆main()称之为主线程,为系统的入口,用于执行整个程序
◆在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与 *** 作系统紧密相关的,先后顺序是不能认为的干预的
◆对同一份资源 *** 作时,会存在资源抢夺的问题,需要加入并发控制
;◆线程会带来额外的开销,如cpu调度时间,并发控制开销
◆每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
继承Thread类,重写run方法
//jdk文档 class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() {//重写run方法 // compute primes larger than minPrime . . . } }
重写run方法,执行该父类(Thread)的start()方法,开启新线程,与主线程异步工作!
package aaa; //创建线程方式:继承THread类,重写run()方法,调用start开启线程 public class MyThread extends Thread{ @Override public void run() { // run方法线程 for (int i = 0; i < 5; i++) { System.out.println("run:"+i); } } public static void main(String[] args) { //创建线程对象 MyThread myThread = new MyThread(); //调用start()开启线程 myThread.start(); //main线程 for (int i = 0; i < 1100; i++) { System.out.println("main:"+i); } } }
可以看到,在main方法遍历1100过程中,可看到另一条新线程正在遍历5
网图下载 (案例)需要下载commons-io-2.6.jar.
实现代码:
package aaa; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //联系Thread 实现多线程下载图片 public class MyThread1 extends Thread { private String url;//网络地址 private String name;//文件名 public MyThread1(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("下载了:" + url + name); } public static void main(String[] args) { MyThread1 t1 = new MyThread1("https://img-home.csdnimg.cn/images/20201124032511.png", "1.png"); MyThread1 t2 = new MyThread1("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "2.png"); MyThread1 t3 = new MyThread1("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "3.png"); t1.start(); t2.start(); t3.start(); } } //下载器 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"); } } }
运行打印
由后台打印可以看出,进行下载的图片并不是按1,2,3的顺序下载的,说明这3张图片是3个不同的线程进行了下载。
不建议使用:避免OOP单继承局限性(在Java中一个类只能使用extends继承一个父类.)
实现Runnable接口创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:
//jdk文档 class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } } //然后,下列代码会创建并启动一个线程: PrimeRun p = new PrimeRun(143); new Thread(p).start();
实现
package aaa; //创建线程方式2 实现Runnable接口 ,重写run方法,执行线程需要丢入runnable的实现类,调用start public class MyRunnable implements Runnable { @Override public void run() { //run方法线程 for (int i = 0; i < 5; i++) { System.out.println("run:" + i); } } public static void main(String[] args) { //创建线程对象 MyRunnable myRunnable = new MyRunnable(); //创建线程对象,通过线程对象开启我们 的线程,,代理方式 // Thread thread = new Thread(myRunnable); // thread.start(); new Thread(myRunnable).start(); //main线程 for (int i = 0; i < 1100; i++) { if(i / 9 == 0){ System.out.println("main:" + i); }else{ System.out.println("main:"); } } } }
打印:
已经实现了创建新线程运行
稍改动实现
package aaa; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; //联系Thread 实现多线程下载图片 public class MyRunnable1 implements Runnable { private String url;//网络地址 private String name;//文件名 public MyRunnable1(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownLoaders webDownLoader = new WebDownLoaders(); webDownLoader.downLoader(url, name); System.out.println("下载了:" + url + name); } public static void main(String[] args) { MyRunnable1 t1 = new MyRunnable1("https://img-home.csdnimg.cn/images/20201124032511.png", "4.png"); MyRunnable1 t2 = new MyRunnable1("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "5.png"); MyRunnable1 t3 = new MyRunnable1("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "6.png"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); // t1.start(); // t2.start(); // t3.start(); } } //下载器 class WebDownLoaders { //下载方法 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"); } } }
实现了多线程运行
推荐使用:避免单继承局限性,灵活方便,方便同一对象被多个线程使用
并发线程在多线程 *** 作同一对象,出现数据混乱的问题
实现Callable接口了解为主
改变下载图片案例
package domo02; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //线程创建方式:实现callable //可以有返回值 //可以抛出异常 public class TestCallable implements Callable静态代理{ private String url;//网络地址 private String name;//文件名 public TestCallable(String url, String name) { this.url = url; this.name = name; } @Override public Boolean call() { WebDownLoaders webDownLoader = new WebDownLoaders(); webDownLoader.downLoader(url, name); System.out.println("下载了:" + url + name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable t1 = new TestCallable("https://img-home.csdnimg.cn/images/20201124032511.png", "c4.png"); TestCallable t2 = new TestCallable("https://csdnimg.cn/release/blogv2/dist/pc/img/original.png", "5.png"); TestCallable t3 = new TestCallable("https://csdnimg.cn/release/blogv2/dist/pc/img/articleReadEyes.png", "c6.png"); //创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(3); //提交执行 Future r1 = ser.submit(t1); Future r2 = ser.submit(t2); Future r3 = ser.submit(t3); //获取结果 boolean rs1 = r1.get(); boolean rs2 = r2.get(); boolean rs3 = r3.get(); //关闭服务 ser.shutdownNow(); } } //下载器 class WebDownLoaders { //下载方法 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"); } } }
你:真实角色
婚庆公司:代理你,帮你处理结婚的事情
结婚:你实现结婚接口即可
演示:实现静态代理对比Thread
package proxy; //静态代理模式 //真实对象和代理对象都要实现同一个接口 //代理对象要代理真实角色 You //好处 // 代理对象可以做很多真实对象做不了的事情 // 真实对象专注做自己的事情 public class StacticProxy { public static void main(String[] args) { //Thread对象代理了()-> System.out.println("123456")来执行 new Thread(()-> System.out.println("123456")).start(); You you = new You("me");//结婚对象 WeddingCompany weddingCompany= new WeddingCompany(you);//把对象给到代理对象 weddingCompany.HappyMarry(); } } interface Marry { void HappyMarry(); } //你自己 class You implements Marry { private String name; public You(String name) { this.name = name; } @Override public void HappyMarry() { System.out.println(name + "要结婚了"); } } //代理角色 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 before() { System.out.println("结婚之前布置现场"); } private void after() { System.out.println("结婚之后收尾款"); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)