线程(四),线程中断,线程让步,线程睡眠和线程合并,线程 优先级

我会带着你远行 2024-02-17 17:35 123阅读 0赞

首先说明下,最近的文章都是看的好多的博客总结的,感谢那些无私分享的人们:原文地址是:点击打

首先我们来看一下什么是线程中断:

线程中断函数:interrupt 该函数是一个Thread的静态函数,就是将我们正在”进行的”函数进行中断,为什么 我在这里把进行的三个子打上双引号,哈哈我们来看一下代码

  1. public class MyThread extends Thread {
  2. private int i = 0;
  3. public MyThread(String name) {
  4. super(name);
  5. }
  6. @Override public void run() {
  7. while (true){
  8. System.out.println("线程" + Thread.currentThread().getName() + "执行了" + ++i + "次!");
  9. }
  10. }
  11. } 我们自己的线程其实什么也没有 做,只是在run()方法里有一个死循环,我们在启动了我们的线程之后调用我们的线程中断函数那是不是就能把我们的线程进行中断呢,我们来看一下
  12. public class Interrupt {
  13. public static void main(String[] args) throws InterruptedException {
  14. MyThread thread = new MyThread("interrupt");
  15. thread.start();
  16. thread.interrupt();
  17. }
  18. }
  19. 我们在这里创建了一个线程对象进行启动并在启动之后调用该线程的中断函数,来看下效果:
  20. 线程interrupt执行了390863次!
  21. 线程interrupt执行了390864次!
  22. 线程interrupt执行了390865次!
  23. 线程interrupt执行了390866次!
  24. 线程interrupt执行了390867次!
  25. 线程interrupt执行了390868次!
  26. 线程interrupt执行了390869次!
  27. 线程interrupt执行了390870次!
  28. 线程interrupt执行了390871次!
  29. 线程interrupt执行了390872次!
  30. 线程interrupt执行了390873次!
  31. 线程interrupt执行了390874次!
  32. 线程interrupt执行了390875次!
  33. 线程interrupt执行了390876次!
  34. 线程interrupt执行了390877次!
  35. 线程interrupt执行了390878次!
  36. 线程interrupt执行了390879次!
  37. 线程interrupt执行了390880次!
  38. 线程interrupt执行了390881次!
  39. 线程interrupt执行了390882次!
  40. 线程interrupt执行了390883次!
  41. 线程interrupt执行了390884次!
  42. 这个只是其中的一个片段,看来他是在不停的执行啊,为什么呢.原来问题还是出现在这个中断函数上,其实他不是一个中断函数,他就是一个中断标记函数,我们看一下在我们的代码执行,这是个while循环,我们的主线程是执行了启动之后调用了该线程的中断函数,但是子线程没有中断而是继续执行的,,这个就舍是说其实我们的中断函数其实没有中断我们的线程执行,其实他只是标记了我们的线程为中断状态,至于是什么时候中断呢,是不是在子线程执行完毕的时候呢,我们来看一下 :
  43. public class MyThread extends Thread {
  44. private int i = 0;
  45. public MyThread(String name) {
  46. super(name);
  47. }
  48. // @Override public void run() {
  49. // while (true){
  50. // System.out.println("线程" + Thread.currentThread().getName() + "执行了" + ++i + "次!");
  51. // }
  52. // }
  53. @Override public void run() {
  54. while (!isInterrupted()){
  55. System.out.println("线程" + Thread.currentThread().getName() + "执行了" + ++i + "次!");
  56. }
  57. }
  58. } 我们把我们的死循环修改成了要是没有中断函数的调用我们就执行打印数据:
  59. public class Interrupt {
  60. public static void main(String[] args) {
  61. MyThread thread = new MyThread("interrupt");
  62. thread.start();
  63. try {
  64. Thread.sleep(1);
  65. } catch (InterruptedException e) {
  66. e.printStackTrace();
  67. }
  68. thread.interrupt();
  69. }
  70. } 我们启动线程还是这样的,只是我们让我们的照主线程休眠1毫秒:我们来看一下我们的执行结果线程interrupt执行了1次!
  71. 线程interrupt执行了2次!
  72. 线程interrupt执行了3次!
  73. 线程interrupt执行了4次!
  74. 线程interrupt执行了5次!
  75. 线程interrupt执行了6次!
  76. 线程interrupt执行了7次!
  77. 线程interrupt执行了8次!
  78. 线程interrupt执行了9次!
  79. 线程interrupt执行了10次!
  80. 线程interrupt执行了11次!
  81. 线程interrupt执行了12次!
  82. 线程interrupt执行了13次!
  83. 可以看到的事我们的线程成功中断了,那么 我们这个函数:isInterrupted()函数是什么作用呢,其实他就是一个检测函数,返回的是是否当前线程已经结束,我们在子线程调用中断函数标记子线程为 中断的时候,休眠那么子线程是执行这的,他就在检测是否已经中断标记了,没有中断标记就打印,党我们的子线程调用可中断标记,我们的检测函数就检测到我们的线程是标记了线程中断了,就执行中断,中断我们的子线程了.
  84. 接下来我们看一下线程让步:yield(),线程让步呢就是说该线程释放 CPU的所有权,至于CPU选择那个线程继续执行这个就是CPU的决定了,我们是没有办法干预的,而且他是不会交出线程的对向锁的.这个我们在后面分析
  85. public class Yield {
  86. public static void main(String[] args) throws InterruptedException {
  87. MyThread thread1 = new MyThread("thread1");
  88. MyThread thread2 = new MyThread("thread2");
  89. thread1.start();
  90. thread2.start();
  91. Thread.sleep(1);
  92. Thread.sleep(1);
  93. thread1.interrupt();
  94. thread2.interrupt();
  95. }
  96. } 我们创建了两个线程,分别启动然后主线程休眠一秒钟,然后我们来看看我们的线程类:
  97. public class MyThread extends Thread {
  98. private int i = 0;
  99. public MyThread(String name) {
  100. super(name);
  101. }
  102. @Override public void run() {
  103. while (!isInterrupted()) {
  104. System.out.println("线程" + Thread.currentThread().getName() + "执行了" + ++i + "次!");
  105. yield();
  106. }
  107. }
  108. }
  109. 我们的线程还是去检测我们的线程有没有调用中断函数进行标记,每执行打印一次就掉用该线程的yield方法让出CPU,我们来看看 程序的执行情况
  110. 线程thread2执行了4次!
  111. 线程thread1执行了99次!
  112. 线程thread2执行了5次!
  113. 线程thread1执行了100次!
  114. 线程thread2执行了6次!
  115. 线程thread1执行了101次!
  116. 线程thread2执行了7次!
  117. 线程thread2执行了8次!
  118. 这个只是我截取的一部分执行结果,我们可以看到我们的线程之间进行了切换执行,但是他们的切换很没有规律,这个是为什么呢,就是因为该函数yield没有释放掉线程对象的锁,当然我们这里也没有加锁,通俗点就是线程只是让出了CPU资源该线程变为就绪态,至于CPU调用那个线程执行,我们不得控制,但是有一点就是线程是让出了CPU,2号线程也执行了.要是我们加了Synchronized的话,按照我们的分析,线程1和线程2永远不会交叉执行的:我们试试
  119. public class MyThread extends Thread {
  120. List list = new ArrayList();
  121. private int i = 0;
  122. public MyThread(String name, List list) {
  123. super(name);
  124. this.list = list;
  125. }
  126. @Override public synchronized void run() {
  127. while (!isInterrupted()) {
  128. synchronized (this) {
  129. if (i++ < 10) {
  130. list.add(1);
  131. }
  132. yield();
  133. }
  134. }
  135. }
  136. } public class MyThread2 extends Thread {
  137. List list = new ArrayList();
  138. private int i = 0;
  139. public MyThread2(String name, List list) {
  140. super(name);
  141. this.list = list;
  142. }
  143. @Override public synchronized void run() {
  144. while (!isInterrupted()) {
  145. synchronized (this) {
  146. if (i++ < 10) {
  147. list.add(2);
  148. }
  149. yield();
  150. }
  151. }
  152. }
  153. } public class Yield {
  154. public static void main(String[] args) throws InterruptedException {
  155. List<Integer> list = new ArrayList<Integer>();
  156. MyThread thread1 = new MyThread("thread1", list);
  157. MyThread2 thread2 = new MyThread2("thread2", list);
  158. thread1.start();
  159. thread2.start();
  160. for (Integer integer : list) {
  161. System.out.println(integer);
  162. }
  163. thread1.interrupt();
  164. thread2.interrupt();
  165. }
  166. } 好了这个就死我们的这个的测试,我们创建两个线程,但是有一个共同的加锁对象就是我们的list,我们分析下线程可能得到的结果,
  167. 首先启动两个线程,分别是线程1和线程2,线程1在执行的时候调用yield函数让出CPU但是线程2不会取执行,因为没哟让出list 的对象锁,这样的话线程1执行完毕之后,线程1中断释放了对象锁,线程2也中断了所以,打印list中的结果,应该只有1数字.是不是 呢,我们来试试
  168. 1
  169. 1
  170. 1
  171. 1
  172. 1
  173. 1
  174. 1
  175. 1
  176. 1
  177. 1
  178. OK,是没有问题的,但是呢这段代码有个隐含额错误,我们在后面学习探究.这个就是我们的yield函数让出线程的CPU占用,但是不会释放锁哦,只是线程放回到就绪态,至于以后怎么执行就看CPU啦.
  179. 接下来就是我们线程睡眠函数:sleep(),这个函数有两个重载的函数分别是:sleep(long)参数含义是毫秒,sleep(long, int),参数含义是毫秒,纳秒,sleep函数是指当前调用该函数的线程进行睡眠等待设置的时间,当然他也是不会放弃对象锁的,就是说在synchronized指示的代码快中调用sleep的话其他的线程只能等待别无他法,好了我们来看一下把:
  180. public class Sleep {
  181. public static void main(String[] args) {
  182. Object object = new Object();
  183. MyThread1 myThread1 = new MyThread1("T1", object);
  184. MyThread2 myThread2 = new MyThread2("T2", object);
  185. myThread1.start();
  186. myThread2.start();
  187. }
  188. static class MyThread2 extends Thread {
  189. private Object object;
  190. public MyThread2(String name, Object object){
  191. super(name);
  192. this.object = object;
  193. }
  194. @Override public void run() {
  195. synchronized (object){
  196. count();
  197. }
  198. }
  199. }
  200. static class MyThread1 extends Thread{
  201. private Object object;
  202. public MyThread1(String name, Object object) {
  203. super(name);
  204. this.object = object;
  205. }
  206. @Override public void run() {
  207. synchronized (object){
  208. count();
  209. }
  210. }
  211. }
  212. public static void count() {
  213. System.out.println("线程:" + Thread.currentThread().getName() + "执行!");
  214. try {
  215. Thread.sleep(10000);
  216. } catch (InterruptedException e) {
  217. e.printStackTrace();
  218. }
  219. }
  220. } 好了,我们创建了两个线程都是对同一个object对象 进行操作的,但是呢在执行这个加锁的同步代码快的时候需要等待,那么sleep是不会释放掉锁的,所以后来的那个线程必须等待钱一个线程等待结束并释放掉锁....
  221. 好了我们来看第四个方面就是线程合并,join()其实这个名字,大家随便理解下意思就是了,这个函数的意思就是在正在执行到的函数中,调用另一个函数的join()方法,那么该函数停止执行,一致等待别的线程执行结束,这个的举例,请看我的另一篇文章 线程join():线程合并,但是我们也要记住哦,该函数也有好几个重载的函数,join(),join(long)毫秒,join(long, int),毫秒,纳秒
  222. 还有一个就是线程优先级,操作系统的线程优先级有1--10个级别 10最高优先级,1最低优先级,5默认的优先级,操作系统给主线程分配的就是默认的优先级5,Thread了提供了三个常量的优先级MAX_PROPERTY = 10; MIN_PROPERTY = 1; NORM_PROPERTY = 5;还可以使用函数设置线程的优先级:setProperty();

发表评论

表情:
评论列表 (有 0 条评论,123人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线——让步

    让步: 运用Thread.yield()可以实现让步功能; 举例子:A、B两个线程,A让步,则B可以多执行一些,得到的时间片多一些。(未让步前,两个线程分配的时间一般是相等