Process和Thread
程序:指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
进程:是执行程序的一次执行过程,是一个动态的概念。是系统资源分配的单位。
一个进程可以包含有多个线程(如视频中同时听到声音、看到图像,还可以看弹幕)
一个进程至少有一个线程,否则无存在的意义。
线程:CPU调度和执行的单位。
注意:很多多线程是模拟出来,真正的多线程是指有多个CPU,即多核,如服务器。如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,cpu只能执行一个代码,因为切换很快,所以就有同时执行的错觉。
2.核心概念-
线程就是独立的执行路径;
-
在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
-
main()称为主线程,为系统的入口,用于执行整个程序;
-
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序是不能认为干预的;
-
对同一份资源操作时,会存在资源抢夺问题,需要加入并发控制;
-
线程会带来额外的开销,如CPU调度时间,并发控制开销;
-
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
package com.xia.Thread;
public class ThreadTest {
// 继承 Thread 类并重写 run 方法
public static class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("狗尧来学Java");
}
}
}
public static void main(String[] args) {
//创建一个线程
MyThread thread = new MyThread();
//启动线程
thread.start();
for(int i=0;i<1000;i++){
System.out.println("杰哥是最帅的"+i);
}
}
例如:
从网上下载图片保存在指定目录
package com.xia.thread;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习Thread,使用多线程同步下载图片
public class ThreadTest1 extends Thread{
private String url;//图片的网址。
private String name;//图片的名字
public ThreadTest1(String url, String name) {
this.url = url;
this.name = name;
}
//线程的执行体
@Override
public void run() {
WebDownLoader webDownLoader=new WebDownLoader();
webDownLoader.downLoader(url,name,"C:\Users\xj\Desktop\照片\狗尧来");//下载到指定的地方,默认下载到根目录(最后图片会出现在桌面的’照片‘文件夹里,名为’狗尧来1.png‘)
System.out.println("狗尧来,线程执行了"+name);
}
public static void main(String[] args) {
ThreadTest1 t1=new ThreadTest1("https://i0.hdslb.com/bfs/bangumi/image/7131f7b273ec867918fac859dc32508153159b28.png@466w_260h.png","1.png");
ThreadTest1 t2=new ThreadTest1("https://i0.hdslb.com/bfs/bangumi/image/93e371b87f50832c0aceace27ee09d5658bc8434.png@2560w_500h.png","2.png");
ThreadTest1 t3=new ThreadTest1("https://i0.hdslb.com/bfs/bangumi/image/8096fa0ac5d1e0e81feb56dc757a44a8afa3d6f0.png@466w_260h.png","3.png");
//多个线程同时进行,谁先下完谁最先打印
t2.start();
t1.start();
t3.start();
}
}
//下载器
class WebDownLoader{
//下载方法
public void downLoader(String url,String name,String savePath){
try {
URL url1=new URL(url);
File file=new File(savePath+name);
FileUtils.copyURLToFile(url1,file);//通过URL将图片保存在文件里面
} catch (IOException e) {
e.printStackTrace();
System.out.println("狗尧来,这个方法有问题");
}
}
}
2.实现Runnable接口
2.1实现Runnable接口
2.2重写run()方法
2.3执行线程需要创建runnable接口实现类,调用start()方法
代码:
package com.xia.thread;
public class ThreadTest2 implements Runnable{
public void run() {
for (int i=0;i<20;i++){
System.out.println("狗尧来学Java"+i);
}
}
public static void main(String[] args) {
//创建Runnable接口的实现类
ThreadTest2 test2 = new ThreadTest2();
//创建线程对象,通过将runnable接口的实现类放入线程对象,来开启线程
Thread thread = new Thread(test2);
thread.start();
}
}
例:模拟龟兔赛跑
package com.xia.thread;
public class Race implements Runnable{
private static String winner;
public void run() {
for(int i=1;i<=100;i++){
//显示走了多少步
System.out.println(Thread.currentThread().getName()+"-->"+i);
//判断比赛是否结束
boolean is=isGameOver(i);
if(is){
break;
}
}
}
Boolean isGameOver(int i){
//如果有winner就返回true
if(winner!=null){
return true;
}
if(i>=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();
}
}
结果如下:
D:Javabinjava.exe "-javaagent:C:UsersxjDesktopjava学习IntelliJ IDEA 2020.3.3libidea_rt.jar=51317:C:UsersxjDesktopjava学习IntelliJ IDEA 2020.3.3bin" -Dfile.encoding=UTF-8 -classpath D:Javajrelibcharsets.jar;D:Javajrelibdeploy.jar;D:Javajrelibextaccess-bridge-32.jar;D:Javajrelibextcldrdata.jar;D:Javajrelibextdnsns.jar;D:Javajrelibextjaccess.jar;D:Javajrelibextjfxrt.jar;D:Javajrelibextlocaledata.jar;D:Javajrelibextnashorn.jar;D:Javajrelibextsunec.jar;D:Javajrelibextsunjce_provider.jar;D:Javajrelibextsunmscapi.jar;D:Javajrelibextsunpkcs11.jar;D:Javajrelibextzipfs.jar;D:Javajrelibjavaws.jar;D:Javajrelibjce.jar;D:Javajrelibjfr.jar;D:Javajrelibjfxswt.jar;D:Javajrelibjsse.jar;D:Javajrelibmanagement-agent.jar;D:Javajrelibplugin.jar;D:Javajrelibresources.jar;D:Javajrelibrt.jar;C:UsersxjIdeaProjectsJedis01targetclasses;C:Usersxj.m2repositoryredisclientsjedis3.2.0jedis-3.2.0.jar;C:Usersxj.m2repositoryorgslf4jslf4j-api1.7.25slf4j-api-1.7.25.jar;C:Usersxj.m2repositoryorgapachecommonscommons-pool22.6.2commons-pool2-2.6.2.jar;C:Usersxj.m2repositorycomalibabafastjson1.2.62fastjson-1.2.62.jar;C:Usersxj.m2repositorycommons-iocommons-io2.4commons-io-2.4.jar com.xia.thread.Race 狗宗弟-->1 狗尧来-->1 狗宗弟-->2 狗尧来-->2 狗宗弟-->3 狗尧来-->3 狗宗弟-->4 狗尧来-->4 狗宗弟-->5 狗尧来-->5 狗宗弟-->6 狗尧来-->6 狗宗弟-->7 狗尧来-->7 狗尧来-->8 狗宗弟-->8 狗尧来-->9 狗宗弟-->9 狗尧来-->10 狗宗弟-->10 狗尧来-->11 狗宗弟-->11 狗尧来-->12 狗尧来-->13 狗尧来-->14 狗宗弟-->12 狗尧来-->15 狗宗弟-->13 狗尧来-->16 狗宗弟-->14 狗尧来-->17 狗尧来-->18 狗尧来-->19 狗尧来-->20 狗宗弟-->15 狗尧来-->21 狗尧来-->22 狗宗弟-->16 狗尧来-->23 狗宗弟-->17 狗尧来-->24 狗宗弟-->18 狗尧来-->25 狗尧来-->26 狗尧来-->27 狗宗弟-->19 狗尧来-->28 狗宗弟-->20 狗尧来-->29 狗宗弟-->21 狗尧来-->30 狗宗弟-->22 狗尧来-->31 狗宗弟-->23 狗尧来-->32 狗宗弟-->24 狗尧来-->33 狗宗弟-->25 狗尧来-->34 狗宗弟-->26 狗尧来-->35 狗宗弟-->27 狗宗弟-->28 狗尧来-->36 狗宗弟-->29 狗尧来-->37 狗尧来-->38 狗尧来-->39 狗宗弟-->30 狗尧来-->40 狗尧来-->41 狗尧来-->42 狗宗弟-->31 狗尧来-->43 狗尧来-->44 狗尧来-->45 狗尧来-->46 狗尧来-->47 狗宗弟-->32 狗尧来-->48 狗宗弟-->33 狗宗弟-->34 狗宗弟-->35 狗尧来-->49 狗宗弟-->36 狗尧来-->50 狗宗弟-->37 狗尧来-->51 狗宗弟-->38 狗宗弟-->39 狗宗弟-->40 狗宗弟-->41 狗宗弟-->42 狗宗弟-->43 狗宗弟-->44 狗尧来-->52 狗宗弟-->45 狗宗弟-->46 狗尧来-->53 狗宗弟-->47 狗尧来-->54 狗尧来-->55 狗宗弟-->48 狗尧来-->56 狗宗弟-->49 狗尧来-->57 狗尧来-->58 狗宗弟-->50 狗尧来-->59 狗尧来-->60 狗宗弟-->51 狗尧来-->61 狗宗弟-->52 狗尧来-->62 狗宗弟-->53 狗尧来-->63 狗宗弟-->54 狗尧来-->64 狗宗弟-->55 狗尧来-->65 狗宗弟-->56 狗尧来-->66 狗宗弟-->57 狗尧来-->67 狗宗弟-->58 狗尧来-->68 狗宗弟-->59 狗尧来-->69 狗宗弟-->60 狗尧来-->70 狗宗弟-->61 狗尧来-->71 狗尧来-->72 狗宗弟-->62 狗尧来-->73 狗宗弟-->63 狗尧来-->74 狗宗弟-->64 狗尧来-->75 狗宗弟-->65 狗尧来-->76 狗宗弟-->66 狗尧来-->77 狗宗弟-->67 狗尧来-->78 狗宗弟-->68 狗尧来-->79 狗宗弟-->69 狗尧来-->80 狗宗弟-->70 狗尧来-->81 狗宗弟-->71 狗宗弟-->72 狗尧来-->82 狗宗弟-->73 狗宗弟-->74 狗尧来-->83 狗宗弟-->75 狗尧来-->84 狗宗弟-->76 狗尧来-->85 狗宗弟-->77 狗尧来-->86 狗宗弟-->78 狗尧来-->87 狗宗弟-->79 狗尧来-->88 狗宗弟-->80 狗尧来-->89 狗宗弟-->81 狗尧来-->90 狗宗弟-->82 狗尧来-->91 狗尧来-->92 狗宗弟-->83 狗尧来-->93 狗尧来-->94 狗尧来-->95 狗宗弟-->84 狗宗弟-->85 狗宗弟-->86 狗尧来-->96 狗尧来-->97 狗宗弟-->87 狗尧来-->98 狗宗弟-->88 狗尧来-->99 狗宗弟-->89 狗尧来-->100 狗宗弟-->90 winner is 狗尧来 Process finished with exit code 0以上两种方式的比较: 继承 Thread 类
1.子类继承 Thread 类具备多线程能力
- 启动线程:子类对象 .start()
- 不建议使用:避免 OOP 单继承局限性
2.实现 Runnable 接口
- 实现接口 Runnable 具有多线程能力
- 启动线程:传入目标对象+Thread对象.start()
- 推荐使用:避免单继承局限性,方便同一个对象被多个线程使用。
ExecutorService ser = Executors.newFixedThreadPool(线程数);
提交执行
Future<返回值类型> r = ser.submit(线程名);
获取结果
类型 res=r.get();
关闭服务
ser.shutdownNow();
总结:
优点:1.可以定义返回值;2.能抛出异常
缺点:相比而言较为麻烦
狂神说多线程笔记



