ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java:学习什么是多线程

2021-08-27 11:01:07  阅读:163  来源: 互联网

标签:执行 Java int 学习 MyThread 线程 runTime 多线程 public


线程是什么

进程是对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,int,学习,MyThread,线程,runTime,多线程,public
来源: https://www.cnblogs.com/davidFB/p/15189482.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有