多线程

来源:互联网 发布:矩阵乘法结合律 编辑:程序博客网 时间:2024/05/20 21:20


  1、进程、线程概念

    进程:一个正在执行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
    线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。
    注:一个进程中至少有一个线程。
   【 J VM  启动时(通过命令行参数java启动)会有一个java.exe进程。该进程中至少有一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。扩展:更加细节的说明jvm,其实jvm启动不止一个线程,还有负责垃圾回收机制的线程。】
  2、创建线程方式有两种
    第一种方式:继承Thread类。
   步骤:
        1,定义类继承Thread。

        2,复写Thread类中的run方法。

    目的:将自定义代码存储在run方法中,让线程通过start方法启动后来运行。
  3,调用线程的start方法,

    该方法两个作用:启动线程,调用run方法。

     线程创建:

public class MultiThread {        public static void main(String[] args) {          //创建并启动线程一          //new Demo().start();                    //创建并启动线程二          new Thread(new Demo2()).start();                    //主线程执行程序          for(int i=0; i<1000; i++) {              System.out.println(Thread.currentThread().getName() + ": The world " + i);          }      }  }  //定义线程的第一种方法:继承自Thread类  class Demo extends Thread {      public void run() { //封装要运行的代码          for(int i=0; i<1000; i++) {              System.out.println(Thread.currentThread().getName() + ": Hello java " + i);          }      }  }  //定义线程的第二种方法:实现Runnable接口  class Demo2 implements Runnable {      public void run() { //封装要运行的代码          for(int i=0; i<1000; i++) {              System.out.println(Thread.currentThread().getName() + ": Hello java " + i);          }      }  }  
     实现方式和继承方式的区别?
     1、继承Thread,线程运行代码存放在Thread子类run方法中
        实现Runnable,线程运行代码存放在Runnable接口子类run方法中
     2、实现方式避免了java单继承的局限性。
     

     在定义线程类时,建议使用实现方式


     多窗口卖票示例:

public class SaleTicket {        public static void main(String[] args) {          Ticket t = new Ticket();          new Thread(t).start();          new Thread(t).start();          new Thread(t).start();          new Thread(t).start();      }    }    class Ticket implements Runnable {      private int ticket = 100;      public void run() {          while(ticket > 0) {              System.out.println(Thread.currentThread().getName() + "sale : " + ticket--);          }      }  }  
        

     (若继承Thread,则Ticket的ticket属性应为static)

    多线程安全问题:     

    问题出现的状况:
     当多个线程在操作同一个共享数据时,一个线程的多条语句中只执行了一部分,CPU执行权即分配到了其它的线程中执行。导致共享数据错误。
     解决办法:
       单个线程在操作共享数据时,其它线程不能参与进来。
       java用的1、同步代码块来实现安全:

           synchronized(对象) {

                       需要被同步的语句;
          }
    对象如同锁,没有锁的线程就算取得了CPU的执行权也不能执行。
    线程加锁带来的弊端:要有锁对象,所以耗资源;要判断锁,所以效率稍减。 
   

   2、同步函数
       public synchronized void method(Type args) {
                  需要被同步的语句; 
       }

     同步非静态函数用的锁是this。如果同步静态函数:所用的锁不是this,因为静态方法中不能出现this。用的是 类名.class是Class类型对象。 如果一个程序中有安全问题,使用同步时应注意:

     1、明确多线程运行代码(一般为run方法里调用的语句,以及其附带语句(调用了其它的方法))有哪些 2、明确共享数据为何 3、明确运行代码中有哪些语句操作共享数据
 
    使用同步还会出安全问题:此时定为同步的两个前提条件中的一个不满足所造成:1、必须有两个或两个以上的线程 2、必须是多个线程使用同一把锁。

     多线程通信:

     

<span style="color:#666666;">public class ThreadCommunication{        public static void main(String[] args) {          Res r = new Res();          new Thread(new Input(r)).start();          new Thread(new Output(r)).start();      }    }  //共享资源  class Res {      private String name;      private String sex;      private boolean flag = false;      //设置方法      public synchronized void set(String name, String sex){          if(flag)//flag=true表示设置过的还未打印,有数据则等待              try{this.wait();}catch(InterruptedException e){e.printStackTrace();}          this.name = name;          this.sex = sex;          flag = true;          this.notify();      }      //打印方法      public synchronized void out(){          if(!flag)              try{this.wait();}catch(InterruptedException e){e.printStackTrace();}          System.out.println(name + ".........." + sex);          flag = false;          this.notify();      }  }  //输入线程  class Input implements Runnable{      private Res r;      Input(Res r) {          this.r = r;      }      public void run() {          int x = 0;          while(true) {              if(x==0) {                  r.set("lisi", "man");                                 }              else {                  r.set("丽丽", "女女女女");                                  }              x = (x+1)%2;//控制x在0和1之间不断交替,从而让设置的内容不同。          }      }  }  //输出线程  class Output implements Runnable{      private Res r;      Output(Res r) {          this.r = r;      }      public void run() {          while(true) {              r.out();          }      }  }  </span>

0 0