• 1. Java多线程
  • 2. IO部分提问讲一下流的分类 讲一下如何将一个对象写入文件中。 如何从键盘读取内容 随机访问文件使用哪个类解释seek, getFilePointer, skipBytes()方法的含义。 向一个文件中写入的基本过程 从一个文件中读取的基本过程 实现线程的二种方式 根据自已理解讲一下线程和进程的区别 Thread.sleep()和Thread.yield()的含义 讲一下线程状态和生命周期 课堂练习,卖票程序为什么可以卖到-1张和-2张票。 同步即(synchronized)的应用场景 Wait和notify的含义和注意事项。 如何停止一下线程2018/10/152Java多线程
  • 3. Java多线程进程与线程概念 创建和启动Java线程 线程状态和线程控制 多线程的互斥与同步 线程的通讯 死锁的概念2018/10/153Java多线程
  • 4. 进程与线程进程一般是对操作系统而言的。例如,你打开word编辑文档,同时打开outlook收取邮件。我们可以说这时系统内有两个进程在运行。即多个程序几乎在同一时间执行多个任务。 线程一般是对某一程序而言的。如上例,你打开outlook收新邮件的同时,还可以看已下载的邮件,这两件事没有相互干扰,那么我们说此时这一程序中至少有两个线程在运行。即每一个程序在同一时间内执行多个任务。2018/10/154Java多线程
  • 5. 进程与线程从逻辑的观点来看,多线程意味着一个程序的多行语句同时执行,但是多线程并不等于多次启动一个程序,操作系统也不会把每个线程当作独立的进程来对待: 2018/10/155Java多线程
  • 6. 进程与线程两者的粒度不同,是两个不同层次上的概念。进程是由操作系统来管理的,而线程则是在一个程序(进程)内。 (可以看看win2000的任务管理器) 不同进程的代码、内部数据和状态都是完全独立的,而一个程序内的多线程是共享同一块内存空间和同一组系统资源,有可能互相影响。 2018/10/156Java多线程
  • 7. 多线程单线程多线程进程传统进程多线程进程2018/10/157Java多线程
  • 8. 线程和多线程线程的概念2018/10/158Java多线程
  • 9. 线程的调度调度策略的类型有二种 时间片 抢占式:高优先级的线程抢占CPU Java的调度方法 同优先级线程组成先进先出队列,使用时间片策略 对高优先级,使用优先调度的抢占式策略 122018/10/159Java多线程
  • 10. 线程虚拟的CPU,由java.lang.Thread类封装和虚拟CPU来实现。 CPU所执行的代码,传递给Thread类对象。 CPU所处理的数据,传递给Thread类对象。代 码数 据虚拟CPUJava线程模型2018/10/1510Java多线程
  • 11. 创建线程(二种方式及比较)通过java.lang.Thread来创建一个线程 Thread的常用构造器: Thread() Thread(Runnable target) Thread(Runnable target, String name) 并指定线程名称 Thread(String name) 2018/10/1511Java多线程
  • 12. 启动线程每个线程都是通过某个特定Thread对象所对应的方法run( )来完成其操作的,方法run( )称为线程体。 使用start()方法,线程进入Runnable(可运行)状态,它将向线程调度器注册这个线程。 调用start()方法并不一定马上会执行这个线程,正如上面所说,它只是进入Runnable 而不是Running。 注意,不要直接在程序中调用线程的run()方法。 2018/10/1512Java多线程
  • 13. 创建并启动线程例子(例:TestThread) public class TestThread extends Thread{ public void run(){ for(int i = 0;i<100;i++) System.out.println("Count:"+i); } public static void main(String[] args){ TestThread tt = new TestThread(); //注意,不要直接调用run方法 tt.start(); } } ThreadOneTypeTest.java2018/10/1513Java多线程
  • 14. 使用Runnable接口优点是由于继承了Thread后,类再不能继承别的类,所以一般我们采用实现Runnable接口的方法来创建线程。 提供一个实现接口Runnable的类,实现run()方法。 得到这个类的实例A。 New 一个Thread对象,同时A作为参数传入。 例如:Thread runner=new Thread(A); 调用start启动线程 例如:runner.start();2018/10/1514Java多线程
  • 15. 用Runnable创建线程(例: RunnableThread )public class RThread implements Runnable{ //实现接口Runnable中的run方法 public void run(){ for (int k = 0;k<10;k++){ System.out.println("Count:"+k); } } … … } Runnable2018/10/1515Java多线程
  • 16. Runnable接口 使用Runnable接口 可以将CPU,代码和数据分开,形成清晰的模型;通过Thread构造一个虚拟CPU 还可以从其他类继承; 直接继承Thread类 不能再从其他类继承; 编写简单,可以直接操纵线程,无需使用Thread.currentThread()。2018/10/1516Java多线程
  • 17. 线程的调度Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪些线程来执行。 2018/10/1517Java多线程
  • 18. 线程的调度下面几种情况下,当前线程会放弃CPU: 线程调用了yield(),sleep()方法主动放弃; 由于当前线程进行I/O访问,外存读写,等待用户输入等操作,导致线程阻塞; 为等候一个条件变量,线程调用wait()方法; 抢先式系统下,有高优先级的线程参与调度2018/10/1518Java多线程
  • 19. 线程的优先级线程的优先级用数字来表示,范围从1到10,即Thread.MIN_PRIORITY到Thread.MAX_PRIORITY。一个线程的缺省优先级是5,即Thread.NORM_PRIORITY。下述方法可以对优先级进行操作:   int getPriority(); //得到线程的优先级   void setPriority(int newPriority);   //当线程被创建后,可通过此方法改变线程的优先级 注意:并不是所有的操作系统都支持所有级别。 SimplePriorities.java2018/10/1519Java多线程
  • 20. 线程让步和睡眠 对于程序员来说,在编程时要注意给每个线程执行的时间和机会,主要是通过让步(yield()方法)或者让线程睡眠的办法(调用sleep()方法)来让当前线程暂停行一段时间,然后由其它线程来争夺执行的机会。 TestThread5.java 示例 TestThread3.java2018/10/1520Java多线程
  • 21. 线程的join方法(例:TestJoin)Thread API 包含了等待另一个线程完成的方法:join() 方法。当调用 join() 时,调用线程将阻塞,直到目标线程完成为止。 join() 通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有的小问题都得到处理后,再调用主线程来进一步操作。 isAlive 方法,判断线程是否在活动状态,返回布尔值。 2018/10/1521Java多线程
  • 22. 线程的join方法(例:TestJoin) JoinThread r = new JoinThread(); Thread t = new Thread(r); t.start(); try{ t.join(); }catch(InterruptedException e){ } TestJoin.java 2018/10/1522Java多线程
  • 23. Daemon线程(守护线程或精灵线程)守护线程是为其它线程提供服务的线程,它一般应该是一个独立的线程,它的run()方法是一个无限循环。 可以用方法public boolean isDaemon()确定一个线程是否守护线程,也可以用方法public void setDaemon( boolean )来设定一个线程为守护线程。 守护线程与其它线程的区别是,如果守护线程是唯一运行着的线程,程序会自动退出。 典型的如隐藏的系统线程如垃圾收集线程 simpleDaemon.java2018/10/1523Java多线程
  • 24. 线程状态RunnableRunningBlockedNewstart()run() 运行完毕线程调度阻塞事件解除阻塞Dead2018/10/1524Java多线程
  • 25. 线程的启动和调度2018/10/1525Java多线程
  • 26. 线程控制方法说明start()线程方法,新建的线程进入Runnable状态 yield()线程静态方法,放弃执行,回到Runnable状态,使其他优先级不低于此线程的线程有机会先运行sleep()线程静态方法,线程睡眠指定的一段时间,线程进入blocked状态join()线程方法,调用这个方法的线程,会等待加入的子线程完成 wait()对象方法,释放对象锁,线程进入blocked状态,等待被notify或时间到期 notify()/notifyAll()对象方法,唤醒其他的线程2018/10/1526Java多线程
  • 27. 中断线程 1.对于睡眠(sleep())或等待(wait())状态的线,调用interrupt(),在interruptedException中捕获并处理。 2.对于非睡眠或等待状态的线程,调用interrupt()并不产生InterruptedException异常。 Interrupt.java2018/10/1527Java多线程
  • 28. 终止线程终止线程的唯一方法,是使run()执行结束。 结束run()运行的方法: 设置线程运行结束标志(stopFlag) 线程终止后,不能通过start方法重新启动 TestThread4.java2018/10/1528Java多线程
  • 29. 线程组线程组表示一个线程的集合。线程组也可以包含其他线程组。线程组构成一棵树,每个线程组都有一个父线程组。 线程组最有用的一个地方就是控制:只需用单个命令即可完成对整个线程组的操作。 每一个线程都归属于某个线程组,例如在主函数main() 中产生一个线程,则产生的线程属于main这个线程组的一员。简单地说,线程组就是由线程组成。这个类是java.lang.ThreadGroup类。 2018/10/1529Java多线程
  • 30. 常用方法ThreadGroup(String name)           构造一个新线程组。 ThreadGroup(ThreadGroup parent, String name)           创建一个新线程组。 Thread.getThreadGroup()           返回该线程所属的线程组。2018/10/1530Java多线程
  • 31. 线程组2018/10/1531Java多线程
  • 32. suspend()、resume()方法suspend()、resume() 1)    通过suspend()函数,可使线程进入停滞状态。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态。 2)    当调用suspend()函数后,线程不会释放它的"锁标志"。 2018/10/1532Java多线程
  • 33. Thread类常用方法static Thread currentThread() 返回对当前正在执行的线程对象的引用。 String getName() 返回该线程的名称。 int getPriority() 返回线程的优先级。 void interrupt() 中断线程。 static boolean interrupted() 测试当前线程是否已经中断。 boolean isAlive() 测试线程是否处于活动状态。 boolean isDaemon() 测试该线程是否为守护线程。 boolean isInterrupted() 测试线程是否已经中断。 void join() 等待该线程终止。 void join(long millis) 等待该线程终止的时间最长为 millis 毫秒。 void join(long millis, int nanos) 等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。 void setDaemon(boolean on) 将该线程标记为守护线程或用户线程。 void setName(String name) 改变线程名称,使之与参数 name 相同。 void setPriority(int newPriority) 更改线程的优先级。 static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 void stop() 停止线程运行 String toString() 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 static void yield() 暂停当前正在执行的线程对象,并执行其他线程。 2018/10/1533Java多线程
  • 34. 多线程的互斥与同步前面所提到的线程都是独立的,而且异步执行,也就是说每个线程都包含了运行时所需要的数据或方法,而不需要外部的资源或方法,也不必关心其它线程的状态或行为。但是经常有一些同时运行的线程需要共享数据,此时就需考虑其他线程的状态和行为,否则就不能保证程序的运行结果的正确性。 2018/10/1534Java多线程
  • 35. 多线程的互斥与同步(问题的提出原因)卖书程序,100本书 为什么最后第0本书会被卖出,似乎并不是你卖完了,我再来卖。 怎么样解决? ErrorSellBookTest.java 2018/10/1535Java多线程
  • 36. 多线程的互斥与同步几个线程并非顺序交替执行; 必须让一个线程的卖完,才能让另一个线程接着卖。 有何方法? 2018/10/1536Java多线程
  • 37. 关键代码段为解决操作的不完整性问题,在Java 语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。 如何保护数据? 关键状态下,别的线程不能接触数据。 Synchronized(obj){} 关键段 obj 锁对象 rSellBookTest.java2018/10/1537Java多线程
  • 38. 2018/10/1538Java多线程
  • 39. 关键代码段synchronizedsynchronized(lock){ if(bookNumber >0){ System.out.println("已卖出书号"+bookNumber); bookNumber = bookNumber -1; } 1 每个对象上都有一个锁 2 为了执行关键代码段(Synchronized())块,线程需要得到锁,一旦获得锁,对象就不再拥有锁。 3 如果线程要执行synchronized 块,锁不在对象上,线程就阻塞了,直到锁被归还对象。 2018/10/1539Java多线程
  • 40. synchronizedsynchronized 除了象上面讲的放在对象前面限制一段代码的执行外,还可以放在方法声明中,表示整个方法为同步方法,使用this。    public synchronized void push(char c){   …   } 2018/10/1540Java多线程
  • 41. synchronized如果一个线程一直占用一个对象的锁,则其他的线程将永远无法访问该对象,因此,需要在适当的时候,将对象锁归还。 当线程执行到synchronized()块结束时,释放对象锁。 当一个线程调用wait()方法时,它放弃拥有的对象锁并进入blocked 状态。 Syschronized 保证同一时刻只有一个线程在运行。 保护数据的方法: 1、数据私有 2、所有的访问同步化 3、用数据本身做锁 First2018/10/1541Java多线程
  • 42. 常见示例:生产者和消费者示例。 示例 示例未使用wait和notify方式, 缺点 浪费CPU资源 在个别操作系统上不支持 所有的java对象都有一个wait pool,每个pool 都可以容纳线程。 Wait 与notify 都是Object中的方法。 线程协作即线程的通讯2018/10/1542Java多线程
  • 43. wait、notify、notifyAll每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的对待队列是空的。 我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。 当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。 当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。 wait和notify主要用于producer-consumer这种关系中。http://www.sunxin.org2018/10/1543Java多线程
  • 44. wait()方法wait()方法是Object对象的方法,而不是Thread的方法。 wait()方法只可能在synchronized块中被调用。 wait()被调用时,原来的锁对象释放锁,线程进入blocked状态。 wait()被notify()唤醒的线程从wait()后面的代码开始继续执行。2018/10/1544Java多线程
  • 45. Wait实例public class WaitTest { public static void main(String[] args) throws InterruptedException { WaitThread w = new WaitThread();w.start(); System.out.println("main over"); Thread.sleep(3000);w.interrupt(); System.out.println("最终结束"); }} class WaitThread extends Thread{ public void run(){ synchronized(this){ System.out.println("wait前"); try { this.wait();//this.wait(2000) System.out.println("wait后"); } catch (InterruptedException e) { System.out.println("发生异常"); e.printStackTrace(); }}}}2018/10/1545Java多线程
  • 46. notify()和notifyAll()只能在synchronized中被调用。 notify它会唤起同一个锁对象上的一个等待线程.但如果有几个线程在等待列表中,它无法决定是哪一个线程被唤醒。调用notifyAll,让所有的等待线程都有机会运行。 示例2018/10/1546Java多线程
  • 47. Notify实例public class NotifyTest { public static void main(String[] args) throws InterruptedException { NotifyThread w = new NotifyThread ();w.start(); System.out.println("main over");Thread.sleep(3000); System.out.println("notify前"); synchronized(w){w.notify();} System.out.println("已经notify后"); }} class NotifyThread extends Thread{ public void run(){ System.out.println("wait前"); synchronized(this){ try {this.wait(); System.out.println("wait后"); } catch (InterruptedException e) { System.out.println("发生异常"); e.printStackTrace(); }}}}2018/10/1547Java多线程
  • 48. NotifyAll实例public class NotifyAllTest { public static void main(String[] args) throws InterruptedException { Object o = new Object(); NotifyAllThread w = new NotifyAllThread(o,"线程一"); NotifyAllThread w1 = new NotifyAllThread(o,"线程二"); w.start();w1.start();Thread.sleep(3000); synchronized(o){o.notifyAll();//o.notify() 比较一下同notify的不同 } }} class NotifyAllThread extends Thread{ Object o ; NotifyAllThread(Object o,String name){super(name);this.o = o;} public void run(){ synchronized(o){ try {o.wait(); System.out.println("我是:"+this.getName()+"我被叫醒了"); } catch (InterruptedException e) {e.printStackTrace();}}} }2018/10/1548Java多线程
  • 49. 死锁死锁 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁 如:哲学家问题(thinking or eating),用筷子吃饭的问题。2018/10/1549Java多线程
  • 50. 死锁AB2018/10/1550Java多线程
  • 51. 死锁代码示例:线程A中 Synchronized(a){ syschronized(b){ } } 线程B中 Synchronized(b){ synchronized(a) } 示例 2018/10/1551Java多线程
  • 52. volatilevolatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。 volatile boolean a=true; While(a){System.out.println(“hello”); } 如上程序未必会每次都会检测a的值,因为他认为while中没有地方改变a,所以就有可能不去检测,volatile就是告诉说,每次执行前一定要去检测a,a是易变的。2018/10/1552Java多线程
  • 53. transienttransient 变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。 Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。 2018/10/1553Java多线程
  • 54. 掌握重点线程和进程的概念 线程的几种状态 线程控制的方法 多线程的互斥与同步 如何实现多线程协作 死锁的概念 2018/10/1554Java多线程
  • 55. 作业体会并实现通过继承Thread类创建线程,并实现下述输出结果:一个线程连续输出26个大写字母A-Z,另一个线程输出26个小写字母a-z; 创建两个线程,一个每3秒打印出线程名和当前时间,另一个每1秒打印出线程名和当前时间 创建两个线程的实例,分别将一个数组从小到大和从大到小排列.输出结果 编写两个线程,共享数据StringBuffer。一个向StringBuffer添加数据,一个从StringBuffer读取数据,如果StringBuffer中没有数据则等待 2018/10/1555Java多线程
  • 56. ThreadLocal2018/10/1556Java多线程
  • 57. ThreadLocal2018/10/1557Java多线程