首页 > 代码库 > Java线程机制

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();            }}