进程是对CPU的抽象,而线程更细化了进程的运行流程
先看一下这个图
线程和进程的关系有
进程中就是线程在执行,所有(主)线程执行完了进程也就结束了
多个线程从1秒钟是同时运行完成,从1纳秒(或是更小的单位)看是排队执行
在不断运行的进程中(没有IO操作),使用多个线程并没有提高进程的执行效率,还有所降低
为什么需要多线程
我第一次使用线程是在学习BIO和多线程进行通信时
服务端每次接收到一个客户端的请求就创建一个线程(虽然可以使用tomcat和Netty大大优化了BIO,但它们也使用了多线程)
就这个用法而言,难道不能用多进程代替多线程进行通信吗(不知道提出这个问题是不是太笨了)
我的理解是:
多个客户端和服务端通信时,服务端有很多资源是多个客户端共用的
如果使用多进程,也就是运行很多个服务端,相同服务端就得存放相同的资源在电脑内存中,太浪费空间了(如果是为了防止故障存在多台机器肯定就不浪费)
所以创建了线程这个概念去共用进程的资源
线程需要什么
业务场景还是在通信中
服务端线程需要在客户端发消息过来时及时响应,至于怎么响应肯定就写在自己的代码逻辑里
所以线程需要一段可以执行的代码块
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 }