线程是什么

进程是对CPU的抽象,而线程更细化了进程的运行流程

先看一下这个图

线程和进程的关系有

  1. 进程中就是线程在执行,所有(主)线程执行完了进程也就结束了
  2. 多个线程从1秒钟是同时运行完成,从1纳秒(或是更小的单位)看是排队执行
  3. 在不断运行的进程中(没有IO操作),使用多个线程并没有提高进程的执行效率,还有所降低

为什么需要多线程

我第一次使用线程是在学习BIO和多线程进行通信时
服务端每次接收到一个客户端的请求就创建一个线程(虽然可以使用tomcat和Netty大大优化了BIO,但它们也使用了多线程)

就这个用法而言,难道不能用多进程代替多线程进行通信吗(不知道提出这个问题是不是太笨了)

我的理解是:

  1. 多个客户端和服务端通信时,服务端有很多资源是多个客户端共用的
  2. 如果使用多进程,也就是运行很多个服务端,相同服务端就得存放相同的资源在电脑内存中,太浪费空间了(如果是为了防止故障存在多台机器肯定就不浪费)
  3. 所以创建了线程这个概念去共用进程的资源

线程需要什么

  业务场景还是在通信中

  • 服务端线程需要在客户端发消息过来时及时响应,至于怎么响应肯定就写在自己的代码逻辑里

    • 所以线程需要一段可以执行的代码块
  • A发消息,就得切换到与A通信的线程,B发消息,就得切换到与B通信的线程,线程就得不停的切换
    • 所以CPU得知道哪个线程和A通信等,就得给线程个ID好辨认

总之线程还需要各种各样我没学过的东西。

下面根据自己的理解,实现一个简单的用户线程

用户线程:如果里面有一个线程执行不下去了(等待输入、运行报错、死循环),操作系统并不认识用户线程,只认识用户进程,会让整个用户进程执行不下去

实现一个简单的用户线程

线程的数据结构

MyThread.java

 1 import java.lang.reflect.Constructor;
2 import java.lang.reflect.InvocationTargetException;
3 import java.lang.reflect.Method;
4
5 public class MyThread<T> {
6
7 private int Id;//区分各个线程的标识符
8 private int runTime;//线程当前可以运行的时间片
9 private int totalTime; //线程总共需要运行的时间
10 private int priority;//线程的优先级
11 //交给线程执行的代码块,用一个对象参数替代
12 public T data;
13
14 public MyThread() {
15 }
16
17 public MyThread(int id, int totalTime,int priority, T data) {
18
19 this.Id = id;
20 // this.runTime = runTime;
21 this.totalTime = totalTime;
22 this.runTime = totalTime/2;//固定线程每次运行时间片是总时间的二分之一,方便测试
23 this.priority = priority;
24 this.data = data;
25 }
26
27 public void run(){
28
29 try {
30
31 System.out.println("线程id:"+Id);
32 System.out.println("剩余时间片:" + runTime);
33 System.out.println("线程优先级:"+priority);
34
35 //使用java的反射机制,执行代码块的内容
36 Class<?> clazz = data.getClass();
37 Constructor constructor = clazz.getDeclaredConstructor();
38 Object object = constructor.newInstance();
39
40 Method method = clazz.getMethod("hello");
41 method.invoke(object);
42
43 //每执行一次,线程总时间减少
44 //运行的时间片不变
45 totalTime-=runTime;
46 // 判断线程运行总时间是否快要结束了
47 runTime = Math.min(totalTime,runTime);
48
49 } catch (NoSuchMethodException e) {
50 e.printStackTrace();
51 } catch (InvocationTargetException e) {
52 e.printStackTrace();
53 } catch (InstantiationException e) {
54 e.printStackTrace();
55 } catch (IllegalAccessException e) {
56 e.printStackTrace();
57 }
58
59 }
60
61 public int getPriority() {
62 return priority;
63 }
64
65 public int getRunTime() {
66 return runTime;
67 }
68
69 public int getTotalTime() {
70 return totalTime;
71 }
72 }

写一个类代替代码块供线程执行

 1 public class MyMethod {
2
3 public MyMethod() {
4
5 }
6
7 public void hello(){
8 System.out.println("hello");
9 }
10
11 }

测试线程的执行

 1 import java.util.Comparator;
2 import java.util.PriorityQueue;
3 public class Test {
4
5 public static void main(String[] args) {
6
7 //由优先队列进行线程的调度,即优先级高的线程先执行,优先级相同采用先入先出算法
8 PriorityQueue<MyThread> priorityQueue = new PriorityQueue<>(new Comparator<MyThread>() {
9 @Override
10 public int compare(MyThread o1, MyThread o2) {
11 return o2.getPriority() - o1.getPriority();
12 }
13 });
14
15 MyMethod method = new MyMethod();
16 //创建三个线程
17 MyThread<MyMethod> myThread = new MyThread<>(1,3,5,method);
18 MyThread<MyMethod> myThread1 = new MyThread<>(2,3,5,method);
19 MyThread<MyMethod> myThread2 = new MyThread<>(3,2,10,method);
20 //线程进入队列
21 priorityQueue.offer(myThread);
22 priorityQueue.offer(myThread1);
23 priorityQueue.offer(myThread2);
24
25 //在循环中不断的执行线程
26
27 while (!priorityQueue.isEmpty()){
28
29 MyThread<MyMethod> myThreadRun = priorityQueue.poll();
30
31 myThreadRun.run();
32
33 //线程总时间不为0,进入队列等待下次执行
34 if (myThreadRun.getTotalTime() != 0){
35 priorityQueue.offer(myThreadRun);
36 }
37 }
38
39 System.out.println("线程都执行完了,进程也就结束了");
40 }
41 }

执行结果

总结

  1. 这个用户线程的例子实现的不好
  2. 例子中总共有四个线程,主线程担任了一个调度线程的职责
  3. 在操作系统中,线程的执行
    • 操作系统会不断主动去询问线程的时间片结束没,一旦结束就将线程换下
  4. 多线程排队执行出现竞争
    • 一个线程执行一个打印命令,对应了CPU中的多条指令
    • 如果指令没执行完,切换到了其他线程,再换回来执行指令,就会出现一种竞争的情况

Java:学习什么是多线程的更多相关文章

  1. Java学习手记2——多线程

    一.线程的概念 CPU执行程序,就好比一个人在干事情一样,同一个时间你只能做一件事情,但是这样的效率实在是太低了,在你用电脑的时候,听歌就不能浏览网页,看电影就不能下载视频,你想想是不是很蛋疼. 所以 ...

  2. 【原】Java学习笔记032 - 多线程

    package cn.temptation; public class Sample01 { public static void main(String[] args) { /* * [进程]:正在 ...

  3. Java学习笔记之——多线程

    多线程编程 程序: 进程:一个程序运行就会产生一个进程 线程:进程的执行流程,一个进程至少有一个线程,称为主线程 如:QQ聊着天,同时在听音乐 一个进程可以有多个线程,多个线程共享同一个进程的资源 线 ...

  4. java学习之路--多线程实现的方法

    1 继承Thread类 继承Thread类的方法尽管被我列为一种多线程实现方式,但Thread本质上也是实现了Runnable接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过Th ...

  5. Java学习笔记:多线程(一)

    Java中线程的五种状态: 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked) 凋亡状态(Dead) 其中阻塞状态(Blocked)又分为三种: ...

  6. Java学习之并发多线程理解

    1.线程简介: 世间万物会同时完成很多工作,如人体同时进行呼吸.血液循环.思考问题等活动,用户既可以使用计算机听歌也可以使用它打印文件,而这些活动完全可以同时进行,这种思想在Java中称为并发,而将并 ...

  7. java学习笔记(5)多线程

    一.简介(过段时间再写,多线程难度有点大) --------------------------------------- 1.进程:运行时的概念,运行的应用程序 2.线程:应用程序内部并发执行的代码 ...

  8. Java 学习笔记(11)——多线程

    Java内部提供了针对多线程的支持,线程是CPU执行的最小单位,在多核CPU中使用多线程,能够做到多个任务并行执行,提高效率. 使用多线程的方法 创建Thread类的子类,并重写run方法,在需要启动 ...

  9. Java学习笔记:多线程(二)

    与线程生命周期相关的方法: sleep 调用sleep方法会进入计时等待状态,等待时间到了,进入就绪状态. yield 调用yield方法会让别的线程执行,但是不确保真正让出.较少使用,官方注释都说 ...

  10. JAVA学习之路(多线程)---模拟售票(细解)

    首先看题目描述: 假设有火车票100张,创建4个线程模拟4个售票点,每100ms售出一张,打印出售票过程,格式如下: 窗口3:卖出第100张票 窗口4:卖出第99张票 ............ ... ...

随机推荐

  1. Python小白的数学建模课-B4. 新冠疫情 SIR模型

    Python小白的数学建模课-B4. 新冠疫情 SIR模型 传染病的数学模型是数学建模中的典型问题,常见的传染病模型有 SI.SIR.SIRS.SEIR 模型. SIR 模型将人群分为易感者(S类). ...

  2. windows下flutter2.2.3环境搭建

    先上几个必上的网站: 官网: https://flutter.cn/docs/get-started/install/windows 中文资源网(毕竟中文母语,看着轻松): https://flutt ...

  3. python pycharm 正则表达式批量替换

    {accept:application/json, text/plain, */*,accept-encoding:gzip, deflate, br,accept-language:zh-CN,zh ...

  4. ASP.NET保存图片到sql2008

    //将图片转行为二进制的方式,存储到数据库 string name = FileUpload1.PostedFile.FileName; string type = name.Substring(na ...

  5. final修饰符(6)-final类

    final修饰的类不可以有子类,例如:java.lang.Math类就是一个final类,它不可以有子类 子类继承父类,可以访问父类的内部数据,可以重写父类的方法来改变父类方法的实现细节,可能导致不安 ...

  6. Docker搭建Redis5.0并挂载数据

    记录 Docker 搭建 Redis5.0 并挂载数据过程,搭建参考自 Docker Hub 系列文章欢迎访问:https://www.itwxe.com/posts/9e76db89/ 一.简单挂载 ...

  7. Discuz! X3.4 邮件设置 使用qq邮箱发邮件

    1. 在qq邮箱->设置中,获取授权码 2. 在discuz后台配置基础信息 3.  在服务器的防火墙中添加规则,允许访问465端口

  8. TheadLocal与synchronized

    深入比较TheadLocal模式与synchronized关键字 ThreadLocal模式synchronized关键字都用于处理多线程并发访问变量的问题,只是二者处理问题的角度和思路不同. 1)T ...

  9. sql注入之类型及提交注入

    #参数类型 这里说的参数是源码中存在注入的地方. 其中参数类型有:数字.字符.搜索.json等. 其中sql语句干扰符号有:',",%,),}等,过滤首先考虑闭合这些符号,再进行注入测试. ...

  10. ZooKeeper(2181、2171) 未授权访问

    下载地址http://archive.apache.org/dist/zookeeper/zookeeper-3.4.14/ tar -xzvf zookeeper-3.4.14.tar.gz cd ...