Java线程机制

线程简介:

线程是一个程序内部的顺序控制流。
线程和进程的区别:
  每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
  线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,线程切换的开销小。

多进程:
  在操作系统中能同时运行的多个任务。
多线程:
  在同一个应用程序中有多个顺序流同时执行。

Java的线程是通过java.lang.Thread类实现的;JVM启动时会有一个由主方法所定义的线程;可以通过创建Thread的实例来创建新的线程;每个线程都是通过某个特定的Thread对象所对应的run()方法来完成其操作的,run()方法称为线程体。

线程的创建与启动:

第一种:
  1.定义线程类target实现Runnable接口(使用Runnable接口可以为多个线程提供共享数据),其中Runnable中只有一个方法public void run();
  2.Thread my Thread = new Thread(target);
  3.在实现Runnable接口的类的run()方法定义中可以使用Thread的静态方法(currectThread()方法用于获取当前线程的引用)。
第二种:
  1.可以定义一个Thread的子类并重写其run()方法:class MyThread extends Thread{ public void run(){ } } ;
  2.然后生成该类的对象。

线程状态的转换:

                       阻塞解除    
                  <-----------------
                   调度     导致阻塞的事件
                  <----       ---->*阻塞状态
  *创建    *就绪状态    *运行状态     *终止
      ---->       ---->       ---->
      start        调度       运行结束

*标记为线程状态,箭头表示转换过程。

线程控制的基本方法:

isAlive()        判断线程是否还活着,即线程还未终止(上面的阻塞、就绪、运行三个状态)
getPriority()      获得线程的优先级
setPriority()      设置线程的优先级
Thread.sleep()      使当前线程进入休眠状态,并指定睡眠的毫秒数
join()          将当前线程与被调用该方法的线程合并,即等待该线程结束,在回复当前线程的运行
yield()         让出cpu,当前线程进入就绪队列等待调度
wait()          当前线程进入对象的wait pool
notify()/notifyAll()    唤醒对象的wait pool中的一个/所以等待线程

join的例子:

public class TestJoin {
  public static void main(String[] args) {
    MyThread2 t1 = new MyThread2("abcde");
    t1.start();
    try {
        t1.join();
    } catch (InterruptedException e) {}
        
    for(int i=1;i<=10;i++){
      System.out.println("i am main thread");
    }
  }
}
class MyThread2 extends Thread {
  MyThread2(String s){
      super(s);
  }
  
  public void run(){
    for(int i =1;i<=10;i++){
      System.out.println("i am "+getName());
      try {
          sleep(1000);
      } catch (InterruptedException e) {
          return;
      }
    }
  }
}

只有执行完了t1的run()方法时才会继续执行main()方法。

Java的优先级别:

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照线程的优先级决定应调用哪个线程来执行;线程的优先级用数字来表示,范围从1到10,一个线程的缺省优先级是5。
  Thread.MIN_PRIORITY = 1
  Thread.MAX_PRIORITY = 10
  Thread.NORM_PRIORITY = 5

线程同步:

  在Java语言中,引入对象互斥锁的概念,保证共享数据操作的完整性;每个对象都对应于一个可以成为互斥锁的标记;这个标记保证在任意时刻,只有一个线程访问该对象;关键字synchronized用来与对象的互斥锁相联系;当某个对象的synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。


synchronized的用法:

      synchronized (this) {

      }

synchronized还可以放在方法生声明中,表示整个方法为同步方法:

  public synchronized void add(String name){ 

  }

无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

public class TestSync implements Runnable {
  Timer timer = new Timer();
  public static void main(String[] args) {
    TestSync test = new TestSync();
    Thread t1 = new Thread(test);
    Thread t2 = new Thread(test);
    t1.setName("t1"); 
    t2.setName("t2");
    t1.start(); 
    t2.start();
  }
  public void run(){
    timer.add(Thread.currentThread().getName());
  }
}

class Timer{
  private static int num = 0;
  public synchronized void add(String name){ 
      //synchronized (this) {
        num ++;
        try {Thread.sleep(1);} 
        catch (InterruptedException e) {}
        System.out.println(name+", 你是第"+num+"个使用timer的线程");
      //}
  }
}

需要注意的是:

  1.两个线程不可同时执行一个类中被声明了synchronized的方法;
  2.当一个线程正在访问一个类的其中一个被声明为synchronized方法的方法的时候,其他线程可以访问该类中没有声明为synchronized的方法;
  3.一个类中不可以同时有多个被声明为synchronized的方法被执行(一个对象只有一个互斥锁,需要等待另外一个线程释放互斥锁后才可以执行)。

Wait和sleep的区别:

  Wait时,别的线程可以访问锁定的对象(调用wait的方法的时候必须锁定该对象)。
  Sleep时,别的线程不可以访问锁定对象。

死锁的例子:

public class TestDeadLock implements Runnable {
    public int flag = 1;
    static Object o1 = new Object(), o2 = new Object();
    public void run() {
System.out.println("flag=" + flag);
        if(flag == 1) {
            synchronized(o1) {
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized(o2) {
                    System.out.println("1");    
                }
            }
        }
        if(flag == 0) {
            synchronized(o2) {
                try {
                    Thread.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                synchronized(o1) {
                    System.out.println("0");
                }
            }
        }
    }    
    
    public static void main(String[] args) {
        TestDeadLock td1 = new TestDeadLock();
        TestDeadLock td2 = new TestDeadLock();
        td1.flag = 1;
        td2.flag = 0;
        Thread t1 = new Thread(td1);
        Thread t2 = new Thread(td2);
        t1.start();
        t2.start();
        
    }
}


原文地址:https://www.cnblogs.com/mosquito-woo/p/3920348.html