学习笔记-马士兵java- 多线程机制

1. 线程的基本概念

  a. 线程:是一个程序内部的顺序控制流(一个程序的不同执行路径)。(class文件,exe文件--进程--静态概念)

  b. 线程和进程的区别:

    ① 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。

    ② 线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。

    ③ 多进程:在操作系统中能同时运行多个任务(程序)。

    ④ 多线程:在同一应用程序中有多个顺序流同时执行。

  c. Java 的线程是通过 java.lang.Thread 类来实现的。

  d. 主线程:VM(虚拟机) 启动时会有一个由主方法(public static void main(){})所定义的线程。

  e. 可以通过穿件 Thread 的实例来创建新的线程。

  f. 每个线程都是通过某个特定 Thread 对象所对应的方法 run() 来完成其操作的,方法 run() 称为线程体。

  g. 通过调用 Thead 类的 start() 方法来启动一个线程(若调用 run方法,则还在主线程中,执行完 run方法,才继续回到主线程)。

2. 线程的创建和启动

  a. 可以有两种方式穿件新的线程:

    ① 第一种(推荐使用,能用接口不用继承):

      ⑴ 定义线程类,实现 Runnable 接口

      ⑵ Thread myThread = new Thead(target)  // target 为 Runnable 接口类型。

      ⑶ Runnable 中只有一个方法:

        public void run();  // 用以定义线程运行体

      ⑷ 使用 Runnable 接口可以为多个线程提供共享数据。

      ⑸ 在实现 Runnable 接口的类的 run 方法定义中可以使用 Thread 的静态方法:

        public static Thread currentThread()  // 获取当前线程的引用

    ② 第二种(Thread 类本身也实现了 Runnable 接口):

      ⑴ 可以定义一个 Thread 的子类,并重写其 run 方法。如:

        class MyThread extends Thead{

          public void run() {...}

        }

      ⑵ 然后生成该类的对象:

        MyThread myThread = new MyThread(...)

3. 线程的调度和优先级

  a. 线程的状态转换:

线程状态转换 

  b. 线程控制基本方法:

    ⑴ isAlive()  // 判断线程是否还“活”着,即线程是否还未终止。

    ⑵ getPriority()  // 获得线程的优先级数值。

    ⑶ setPriority()  // 设置线程的优先级数值。

    ⑷ Thread.sleep()  // 当前线程睡眠指定毫秒数。

    ⑸ join()  // 将当前线程与该线程“合并”,即等待该线程结束,再回复当前线程的运行。

    ⑹ yield()  // 让出 CPU 当前线程进入就绪队列等待调度。

    ⑺ wait()  // 当前线程进入对象的 wait pool。

    ⑻ notify() / notifyAll()  // 唤醒对象的 wait pool 中的(一个 / 所有)等待的线程。

4. 线程的状态控制

  a. sleep方法:

    ① 可以调用 Thread 的静态方法:

      public static void sleep(long millis) throws InterruptedException  //使得当前线程休眠(暂时停止执行 millis 毫秒,1000毫秒=1秒)

    ② 由于是静态方法,sleep 可以由类名直接调用:

      Thread.sleep(...)

  b. join方法:合并某个线程。

  c. yield方法:让出CPU,给其他线程执行的机会(本身还会执行)。

  d. interrupt() 方法:强制关闭线程(有try...catch...可执行)。

  e. stop()方法:杀死线程(已废弃,直接杀死)。

  f. 让线程停止的最好方法:在线程类内定义 flag ,将其改为 false 以结束 run方法内的 while(flag) 循环。

  g. 线程的优先级(优先级越高,得到 CPU 时间片越多):

    ⑴ Java 提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪个线程来执行。

    ⑵ 线程的优先级用数字表示,范围从 1 到 10,一个线程的缺省优先级是 5.

      Thread.MIN_PRIORITY = 1

      Thread.MAX_PRIORITY = 10

      Thread.NORM_PRIORITY = 5

    ⑶ 使用下属线程方法获得或设置线程对象的优先级:

      ① int getPriority();  // 获得优先级

      ② void setPriority(int newPriority);  // 设置优先级

5. 线程同步

  a. 互斥锁:synchronized(this){...}  (也可作为方法的修饰符,执行方法时,当前对象被锁定)// 锁定当前对象

  b. 在JAVA语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任一时刻,只能有一个县城访问该对象。

  c. 关键字:synchronized 来与对象的互斥锁联系。当某个对象被 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。

    ① synchronized 的使用方法:

      synchronized(this) {

        num++;

        try{Thread.sleep(1);} 

        catch(InterruptedException e){}

        System.out.println(name+",你是第“+num+"个使用timer的线程");

      }

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

      synchronized public void add(String name) {...}

  d. 死锁:A线程锁住a对象,访问b对象;同时,B线程锁住b对象,访问a对象。==> 出现死锁(解决办法之一:把锁的粒度加大,锁住一个包括a,b对象的对象即可)

  e. synchronized 只锁定被修饰的方法内的语句(锁不住成员变量),其他方法仍可继续访问成员变量。即:只保证同一时刻只有一个线程访问被修饰的语句,不保证访问同一资源的其他方法。(解决办法:锁住所有访问同一资源的方法。前一个方法已锁定,后一个方法必须等前一方法执行完才可再锁定)

posted @ 2013-10-28 21:10  被盗的小偷  阅读(143)  评论(0)    收藏  举报