java学习之路17多线程

1.多线程   

    线程是程序执行流的最小单元。是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。  
    多线程的意义就在于使得一个应用程序有多条执行路径,从而提高进程(程序)的执行效率。

2.JAVA中的多线程

2.1概述实现

     JAVA实现多线程的方法有三种: 1)继承Thread实现多线程。2)通过实现Runnable接口方式实现多线程。3)使用ExecutorService、Callable、Future实现有返回结果的多线程。这三种方法的具体实现,在此先不一一赘述,网上有很多有关的博客,不明白的朋友可以去看看。

      JAVA程序的运行原理便是命令去启动JVM,JVM会启动一个进程,该进程会启动一个主线程。然而JVM的启动必然也是多线程的,一般情况下,它最低有两个线程启动了:主线程和垃圾回收线程。

2.2线程生命周期

1)新建        2)就绪        3)运行        4)阻塞        5)死亡

2.3线程的优先级

    线程的调度有两种方式:1)分时调度。2)抢占式调度。JAVA采用的是后者,默认情况下,线程去抢占资源(CPU执行权)。我们可以通过setPriority方法,设置线程的优先级,默认是5,范围为1-10。但是一般情况下,光是设置线程的优先级,不能使得线程有序且高效执行,所以我们还需要学习更多的方法与原理机制。

2.4线程的控制(常见方法)

1)休眠线程        2)加入线程        3)礼让线程        4)后台线程        5)终止线程

2.5多线程的安全问题

    在多线程的环境下,大多时候都是会共享数据,存在多条语句操作共享数据,这样很多时候会出现脏数据。所以为了解决线程的安全的问题,我们可以通过synchronized同步锁对象达到我们的目的。

1)同步代码块

synchronized(对象)

{

    需要被同步的代码块

}

2)同步方法

把同步加在方法上,这里的锁对象是this。

3)静态同步方法

把同步加在方法上。这里的锁是当前类的字节码文件。

PS:JDK5以后的针对线程的锁定操作和释放操作: Lock锁。

3.多线程写一个文件

     如何实现多线程同时或读或写一个文件呢?我们都知道,一个文件在同一时间只能被一个线程读(写),如果要两个线程同时写一个文件,如何有效有序的分配这个临界资源呢?

    下面我将通过一个例子,阐述我的解决方法 -——沉睡唤醒机制。

    需求:两个线程写一个TXT文件,线程1:I love you  线程2:so do I 。保证线程1、2有序执行,一句I love you,对应一句so do I。

第一步,先创建WRFile类。这一步是关键的。

 
  1. package cn.Thread.love;

  2.  
  3. import java.io.FileNotFoundException;

  4. import java.io.IOException;

  5. import java.io.RandomAccessFile;

  6.  
  7. public class WRFile {

  8. //String str;

  9. boolean flag;

  10. public WRFile()

  11. {

  12.  
  13. }

  14. public synchronized void read1()

  15. {

  16. if(this.flag)

  17. {

  18. try {

  19. this.wait();

  20. } catch (InterruptedException e) {

  21.  
  22. e.printStackTrace();

  23. }

  24. }

  25. RandomAccessFile ra = null;

  26. try {

  27. ra = new RandomAccessFile("love.txt", "rw");

  28. ra.seek(ra.length());

  29.  
  30. ra.writeBytes("I love you");

  31. ra.writeBytes("\r\n");

  32. } catch (Exception e) {

  33.  
  34. e.printStackTrace();

  35. }

  36. finally {

  37. try {

  38. ra.close();

  39. } catch (IOException e) {

  40.  
  41. e.printStackTrace();

  42. }

  43. }

  44. //修改标记 唤醒线程

  45. this.flag = true;

  46. this.notify();

  47. }

  48. public synchronized void read2()

  49. {

  50. if(!this.flag)

  51. {

  52. try {

  53. this.wait();

  54. } catch (InterruptedException e) {

  55.  
  56. e.printStackTrace();

  57. }

  58. }

  59. RandomAccessFile ra = null;

  60. try {

  61. ra = new RandomAccessFile("love.txt", "rw");

  62. ra.seek(ra.length());

  63.  
  64. ra.writeBytes("so do I");

  65. ra.writeBytes("\r\n");

  66. } catch (Exception e) {

  67.  
  68. e.printStackTrace();

  69. }

  70. finally {

  71. try {

  72. ra.close();

  73. } catch (IOException e) {

  74.  
  75. e.printStackTrace();

  76. }

  77. }

  78. //修改标记 唤醒线程

  79. this.flag = false;

  80. this.notify();

  81. }

  82.  
  83. }


 

第二步,创建我们的两个线程类,第一个FirstThread。

 
  1. package cn.Thread.love;

  2.  
  3. public class FirstThread implements Runnable {

  4. private WRFile wr = new WRFile();

  5.  
  6. public FirstThread(WRFile wr) {

  7. this.wr = wr;

  8. }

  9. @Override

  10. public void run() {

  11.  
  12. while(true)

  13. {

  14. wr.read1();

  15. }

  16.  
  17. }

  18.  
  19. }

第二个SecondThread

 

 
  1. package cn.Thread.love;

  2.  
  3. public class SecondThrad implements Runnable{

  4. private WRFile wr = new WRFile();

  5. public SecondThrad(WRFile wr) {

  6. this.wr = wr;

  7. }

  8. @Override

  9. public void run() {

  10. while(true)

  11. {

  12. wr.read2();

  13. }

  14. }

  15.  
  16.  
  17. }

第三步,main方法启动线程

 

 
  1. package cn.Thread.love;

  2.  
  3. public class LoveDemo {

  4.  
  5. public static void main(String[] args) {

  6. //创建数据对象

  7. WRFile wr = new WRFile();

  8. //设置和获取类

  9. FirstThread ft = new FirstThread(wr);

  10. SecondThrad st = new SecondThrad(wr);

  11. //线程类

  12. Thread th1 = new Thread(ft);

  13. Thread th2 = new Thread(st);

  14. //启动线程

  15. th1.start();

  16. th2.start();

  17. }

  18.  
  19. }

猜你喜欢

转载自blog.csdn.net/qq_34491508/article/details/81948352