• 1. 线程基础——拟定:任飞 资料提供:任飞,徐令翰Java多线程培训教程2018/10/24
  • 2. 目录线程的创建 线程的同步 线程的常用方法 线程的常用方法调用的注意点 简单进阶
  • 3. 线程的创建线程的创建 继承 Thread类 实现 Runnable接口 继承Thread类不常用,一般都是实现Runnable接口 因为当创建一个类的时候可能继承了其他的类这时候就只能用实现接口的方式创建线程(类只能继承一个,接口可以实现多个)Page 3
  • 4. 线程的创建继承 Thread类 Thread类是一个具体类不是抽象类,该类封装了线程的行为。要创建一个线程,通过覆盖 Thread 的 run() 函数来完成 ,通过调用 Thread 的 start() 函数,该函数再调用 run()。 实现 Runnable接口 此接口只有一个函数,run() Page 4
  • 5. 线程的创建继承Thread类 public class Test extends Thread{       public Test(){       }       public static void main(String args[]){         Test t1 = new Test();         Test t2 = new Test();         t1.start();         t2.start();       }       public void run(){         //do thread's things       }     } Page 5
  • 6. 线程的创建实现Runnable接口 public class Test implements Runnable{       Thread thread1;       Thread thread2;       public Test(){         thread1 = new Thread(this,"1");         thread2 = new Thread(this,"2");       }       public static void main(String args[]){         Test t = new Test();         t.startThreads();       }       public void run(){         //do thread's things       }       public void startThreads(){         thread1.start();         thread2.start();       }     } Page 6
  • 7. 线程的创建 class MyThread extends Thread{     public void run(){      System.out.println("MyThread: run()");     }     public void start(){      System.out.println("MyThread: start()");     }    }    class MyRunnable implements Runnable{     public void run(){      System.out.println("MyRunnable: run()");     }     public void start(){      System.out.println("MyRunnable: start()");     }    }          MyThread myThread = new MyThread();    MyRunnable myRunnable = new MyRunnable();    Thread thread = new Thread(myRunnable);    myThread.start();    thread.start(); 上处程序执行结果是什么?Page 7
  • 8. 线程的创建答案: MyThread: start() MyRunnable: run() 分析: (一)MyThread 继承自 Thread,且覆盖了start()方法,所以当其实例start()时,不会在执行run()方法中的代码。其实这也是个“没用的线程了”。 所以先打印:MyThread: start() 。 (二)MyRunnable 实现了Runnable 接口,Runnable 接口就一个run()方法。 Thread thread = new Thread(myRunnable); 这句代码,根据Runnable 的实例创建了一个Thread实例,该Thread实例的start方法会执行run()方法中的代码。 所以又打印:MyRunnable: run()Page 8
  • 9. 线程的同步 线程的同步 由于同一进程内的多个线程共享内存空间,在Java中,就是共享实例,当多个线程试图同时修改某个实例的内容时,就会造成冲突,因此,线程必须实现共享互斥,使多线程同步。 线程的同步的实现 通过用关键字synchronized(锁)来给共享资源加锁的形式实现。多线程同步的实现最终依赖锁机制。 Page 9
  • 10. 线程的同步 synchronized 的用法 synchronized 的用法: 1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前. 即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候, 当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入. public synchronized int testThread(){…} 2.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块 public int synMethod(int a1) {         synchronized(a1) {          …        }       } Page 10
  • 11. 线程的同步 synchronized 的用法 3.synchronized后面括号里是一对象,此时,线程获得的是对象锁.synchronized (this) 如果线程进入,则得到对象锁,那么别的线程在该类所有对象上的任何操作都不能进行. 4.synchronized后面括号里是类如果线程进入,则线程在该类中所有操作不能进行,包括静态变量和静态方法, class ArrayWithLockOrder { … synchronized(ArrayWithLockOrder.class) {…} … } 实际上,对于含有静态方法和静态变量的代码块的同步,我们通常用4来加锁. Page 11
  • 12. 线程的常用方法 线程的常用方法 join()等待该进程终止 sleep(2000)休眠该进程 interrupt()中断该进程 yield()暂停当前正在运行的线程,执行其他线程 wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 notify()唤醒在此对象监视器上等待的单个线程。notifyAll()唤醒所有Page 12
  • 13. 线程的常用方法 线程的常用方法----Object 由于wait和notify不是属于线程类,而是Object类中的方法,这两个方法都和对象synchronized有关。 如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是current thread了。Page 13
  • 14. 线程的常用方法 线程的常用方法----Thread join()等待该进程终止 sleep(2000)休眠该进程 interrupt()中断该进程 当线程处于非活动状态(wait/join/sleep)时,调用interrupt()会抛出InterruptedException异常 yield()暂停当前正在运行的线程,执行其他线程Page 14
  • 15. 线程的常用方法调用的注意点synchronized和wait()、notify()的关系 有synchronized的地方不一定有wait,notify,但是有wait,notify的地方必有synchronized.也就是必须写在synchronized(obj) {...} 代码段内 这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法 sleep与wait的不同点 sleep并不释放锁,并且sleep的暂停和wait暂停是不一样的。wait会使线程进入obj对象的等待集合中并等待唤醒。 Page 15
  • 16. 线程的常用方法调用的注意点sleep与yield的不同点 yield()方法与sleep()方法相似,只是它不能由用户指定线程暂停多长时间。按照SUN的说法:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。而yield()方法只能使同优先级的线程有执行的机会。 Page 16
  • 17. 线程的常用方法调用的注意点wait(),notify(),notifyAll()的补充 当线程执行了对一个特定对象的wait()调用时,那个线程被放到与那个对象相关的等待池中。此外,调用wait()的线程自动释放对象的锁标志。  对一个特定对象执行notify()调用时,将从对象的等待池中移走一个任意的线程,并放到锁标志等待池中,那里的线程一直在等待,直到可以获得对象的锁标志。notifyAll()方法将从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。只有锁标志等待池中的线程能获取对象的锁标志,锁标志允许线程从上次因调用wait()而中断的地方开始继续运行。 不管是否有线程在等待,都可以调用notify()。如果对一个对象调用notify()方法,而在这个对象的锁标志等待池中并没有线程,那么notify()调用将不起任何作用。    Page 17
  • 18. 简单进阶 Page 18
  • 19. (本页无文本内容)