程序、进程、线程
程序 Programmer
程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
进程 Process
进程是执行程序的一次执行过程,是一个动态的概念。是系统资源分配的单位。
线程 Thread
通常一个进程中有若干个线程(1~n个,最少一个,即主线程main),线程是CPU调度和执行的单位。
注意
很多线程是模拟出来的,在同一时间同一个CPU只能执行一个代码,因为时间片很小,所以有同时执行的错觉。
线程的核心概念
- 线程是独立的执行程序。
- 在程序运行时,即使我们没有创建线程,后台也会有多个线程,如主线程main(),gc线程。
- main()称之为主线程,作为系统的入口,用于执行整个程序。
- 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不可人为干预的。
- 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制。
- 线程会带来额外的开销,如cpu调度时间,并发控制开销。
- 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致。
线程创建
Thread class
继承Thread类
Runnable接口
实现Runnable接口
Callable接口
实现Callable接口
创建线程方法1:继承Thread类
创建方法
自定义线程类继承Thread类
重写run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
package com.canux.study.lesson1; // 创建线程方式1,继承Thread类,重写run方法,调用start方法启动线程 // 线程开启不一定立即执行,由CPU调度执行 public class TestThread extends Thread{ @Override public void run() { // run方法,线程体 for (int i = 0; i < 20; i++) { System.out.println("我的线程"+i); } } public static void main(String[] args) { // 创建一个线程对象 TestThread testThread = new TestThread(); // 调用start方法启动线程 testThread.start(); // main线程体 for (int i = 0; i < 20; i++) { System.out.println("main线程"+i); } } }
下载网图实例1
package com.canux.study.lesson1; 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 name; public TestThread2(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownload webDownload = new WebDownload(); webDownload.download(url,name); System.out.println("下载了文件名为"+name); } public static void main(String[] args) { TestThread2 testThread2_1 = new TestThread2("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","1.jpg"); TestThread2 testThread2_2 = new TestThread2("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","2.jpg"); TestThread2 testThread2_3 = new TestThread2("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","3.jpg"); testThread2_1.start(); testThread2_2.start(); testThread2_3.start(); } } class WebDownload{ public void download(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { System.out.println("io异常,download方法出现问题"); e.printStackTrace(); } } }
创建线程方法2:实现Runnable接口
创建方法
定义MyRunnable类实现Runnable接口
实现Run()方法,编写线程执行体
创建线程对象,调用start()方法启动线程
package com.canux.study.lesson1; //创建线程方式二,实现Runnable接口,重写run()方法,丢入Runnable接口的实现类,调用start()方法启动线程 public class TestThread3 implements Runnable{ @Override public void run() { // 线程执行体 for (int i = 0; i < 20; i++) { System.out.println("我的线程"+i); } } public static void main(String[] args) { // 创建一个线程对象 TestThread3 testThread3 = new TestThread3(); // 丢入接口的实现类,代理 Thread thread = new Thread(testThread3); // 调用start()方法,启动线程 thread.start(); for (int i = 0; i < 20; i++) { System.out.println("main线程"+i); } } }
下载网图实例2
package com.canux.study.lesson1; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; public class TestThread4 implements Runnable{ private String url; private String name; public TestThread4(String url, String name) { this.url = url; this.name = name; } @Override public void run() { WebDownload1 webDownload1 = new WebDownload1(); webDownload1.download(url,name); System.out.println("下载了文件名为"+name); } public static void main(String[] args) { TestThread4 testThread4_1 = new TestThread4("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","1.jpg"); TestThread4 testThread4_2 = new TestThread4("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","2.jpg"); TestThread4 testThread4_3 = new TestThread4("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","3.jpg"); Thread thread1 = new Thread(testThread4_1); thread1.start(); Thread thread2 = new Thread(testThread4_2); thread2.start(); Thread thread3 = new Thread(testThread4_3); thread3.start(); } } class WebDownload1{ public void download(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { System.out.println("io异常,download方法出现问题"); e.printStackTrace(); } } }
创建线程方法3:实现Callable接口
创建方法
- 实现Callable接口,需要返回值类型
- 重写call方法,需要抛出异常
- 创建目标对象
- 创建执行服务 ExecutorService ser = Executors.newFixedThreadPool(1);
- 提交执行 Future result1 = ser.submit(t1);
- 获取结果 boolean r1 = result1.get();
- 关闭服务 ser.shutdownNow();
下载网图实例3
package com.canux.study.lesson1; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.concurrent.*; //线程创建方式3,实现Collable接口 public class TestCallable implements Callable<Boolean> { private String url; private String name; public TestCallable(String url, String name) { this.url = url; this.name = name; } @Override public Boolean call() { WebDownload2 webDownload2 = new WebDownload2(); webDownload2.download(url,name); System.out.println("下载了文件名为"+name); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestCallable testCallable1 = new TestCallable("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","1.jpg"); TestCallable testCallable2 = new TestCallable("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","2.jpg"); TestCallable testCallable3 = new TestCallable("https://exp-picture.cdn.bcebos.com/2a1ecb460596b814e9fce0b043d246fe464e2283.jpg?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_500%2Climit_1%2Fquality%2Cq_80","3.jpg"); // - 创建执行服务,创建线程池 ExecutorService ser = Executors.newFixedThreadPool(3); // - 提交执行 Future<Boolean> result1 = ser.submit(testCallable1); Future<Boolean> result2 = ser.submit(testCallable2); Future<Boolean> result3 = ser.submit(testCallable3); // - 获取结果 boolean r1 = result1.get(); boolean r2 = result2.get(); boolean r3 = result3.get(); // - 关闭服务,销毁线程池 ser.shutdownNow(); } } class WebDownload2{ public void download(String url,String name){ try { FileUtils.copyURLToFile(new URL(url),new File(name)); } catch (IOException e) { System.out.println("io异常,download方法出现问题"); e.printStackTrace(); } } }