1、第15章 线程线程入门同步化议题concurrent套件新增类别 继承Thread 继承java lang Thread类别 并重新定义run 方法实例化您自定义的Thread类别使用start 方法启动线程 继承Thread publicclassEraserThreadextendsThread privatebooleanactive privateStringmask 重新定义run 方法publicvoidrun while isActive System out print mask try 暂停目前的线程50毫秒Thread currentThread sleep 50 catc
2、h InterruptedExceptione e printStackTrace 继承Thread 启动Eraser线程EraserThreaderaserThread newEraserThread eraserThread start Stringpassword scanner next eraserThread setActive false 在JavaSE6中可以使用System console 来取得java io Console物件使用Console物件的readPassword 方法 就可以避免输入的密码被窥视的问题 实作Runnable界面 如果您的类别已经要继承某个类别
3、那么您就不能继承Thread类别继承了Thread类别 您就不能再继承其它类别实作java lang Runnable接口来定义具线程功能的类别Runnable接口中定义一个run 方法要实作在实例化一个Thread对象时 可以传入一个实作Runnable接口的对象作为自变量 实作Runnable界面 publicclassEraserimplementsRunnable 实作Runnableprivatebooleanactive privateStringmask 重新定义run 方法publicvoidrun while isActive System out print mask tr
4、y 暂停目前的线程50毫秒Thread currentThread sleep 50 catch InterruptedExceptione e printStackTrace 实作Runnable界面 Eraser实作Runnable界面Erasereraser newEraser 启动Eraser线程ThreaderaserThread newThread eraser eraserThread start Stringpassword scanner next eraser setActive false Daemon线程 一个Daemon线程是一个在背景执行服务的线程如果所有的非Dae
5、mon的线程都结束了 则Daemon线程自动就会终止从Main方法开始的是一个非Daemon线程如果希望某个线程在产生它的线程结束后跟着终止 要将它设为Daemon线程 Daemon线程 Threadthread newThread 这是匿名类别的写法newRunnable publicvoidrun while true System out print T 设定为Daemon线程thread setDaemon true thread start 使用setDaemon 方法来设定一个线程是否为Daemon线程预设所有从Daemon线程产生的线程也是Daemon线程 线程生命周期 执行st
6、art 之后 线程进入Runnable状态 此时线程尚未真正开始执行必须等待排班器 Scheduler 的排班 线程生命周期 线程有其优先权 由1 Thread MIN PRIORITY 到10 Thread MAX PRIORITY 优先权越高 排班器越优先排入执行 如果优先权相同 则输流执行 Round robin方式 线程生命周期 如果您想要让目前线程礼让一下其它线程 让它们有机会取得执行权 您可以呼叫绪行绪的yield 方法 Threadthread newThread newRunnable publicvoidrun while true yield 暂时让出执行权 thread
7、start 线程生命周期 有几种状况会让线程进入Blocked状态等待输入输出完成呼叫sleep 方法尝试取得对象锁定呼叫wait 方法 线程生命周期 进入Blocked状态 以下的几个对应情况让线程回到Runnable状态输入输出完成呼叫interrupt 取得对象锁定呼叫notify 或notifyAll 线程生命周期 Threadthread newThread newRunnable publicvoidrun try 暂停99999毫秒Thread sleep 99999 catch InterruptedExceptione System out println I minterr
8、upted thread start thread interrupt interruptitrightnow 线程的加入 join 当线程使用join 加入至另一个线程时 另一个线程会等待这个被加入的线程工作完毕 然后再继续它的动作join 的意思表示将线程加入成为另一个线程的流程之一 线程的加入 join ThreadthreadB newThread newRunnable publicvoidrun try catch InterruptedExceptione e printStackTrace threadB start try ThreadB加入ThreadAthreadB jo
9、in catch InterruptedExceptione e printStackTrace 线程的停止 不建议使用stop 来停止一个线程的运行 publicclassSomeThreadimplementsRunnable privatebooleanisContinue true publicvoidterminate isContinue false publicvoidrun while isContinue somestatements 线程的停止 不建议使用stop 来停止一个线程的运行 Threadthread newThread newSomeThread thread
10、start thread interrupt ThreadGroup 每一个线程产生时 都会被归入某个线程群组如果没有指定 则归入产生该子线程的线程群组中可以自行指定线程群组 线程一但归入某个群组 就无法更换群组 ThreadGroup java lang ThreadGroup类别正如其名 可以统一管理整个群组中的线程ThreadGroup中的某些方法 可以对所有的线程产生作用interrupt 方法可以interrupt群组中所有的线程setMaxPriority 方法可以设定群组中线程所能拥有的最大优先权 ThreadGroupthreadGroup1 newThreadGroup gr
11、oup1 ThreadGroupthreadGroup2 newThreadGroup group2 Threadthread1 newThread threadGroup1 group1 smember Threadthread2 newThread threadGroup2 group2 smember ThreadGroup 想要一次取得群组中所有的线程来进行某种操作 可以使用enumerate 方法 Thread threads newThread threadGroup1 activeCount threadGroup1 enumerate threads ThreadGroup u
12、ncaughtException 方法是当群组中某个线程发生非受检例外 Uncheckedexception 时 由执行环境呼叫进行处理 ThreadGroupthreadGroup1 这是匿名类别写法newThreadGroup group1 继承ThreadGroup并重新定义以下方法 在线程成员丢出uncheckedexception 会执行此方法publicvoiduncaughtException Threadt Throwablee System out println t getName e getMessage UncaughtExceptionHandler 可以让您的例外处
13、理类别实作Thread UncaughtExceptionHandler界面 并实现其uncaughtException 方法 publicclassThreadExceptionHandlerimplementsThread UncaughtExceptionHandler publicvoiduncaughtException Threadt Throwablee System out println t getName e getMessage thread1 setUncaughtExceptionHandler handler 同步化 如果一个对象所持有的数据可以被多线程同时共享存取
14、时 您必须考虑到 数据同步 的问题数据同步指的是两份数据整体性 一致性 同步化 同步化 数据的不同步而可能引发的错误通常不易察觉可能是在您程序执行了几千几万次之后 才会发生错误这通常会发生在您的产品已经上线之后 甚至是程序已经执行了几年之后 同步化 publicvoidsetNameAndID Stringname Stringid this name name this id id if checkNameAndIDEqual System out println count illegalnameorID count 同步化 使用 synchronized 关键词 publicsynchr
15、onizedvoidsetNameAndID Stringname Stringid this name name this id id if checkNameAndIDEqual System out println count illegalnameorID count 同步化 物件的锁定 lock 观念 同步化 使用 synchronized 关键词 publicvoidsetNameAndID Stringname Stringid synchronized this this name name this id id if checkNameAndIDEqual System ou
16、t println count illegalnameorID count arraylist参考至一个ArrayList的一个实例synchronized arraylist arraylist add newSomeClass 同步化 同步化确保数据的同步 但所牺性的就是在于一个线程取得对象锁定而占据同步化区块 而其它线程等待它释放锁定时的延迟 wait notify wait notify 与notifyAll 是由Object类别所提供的方法宣告為 final 在同步化的方法或区块中呼叫wait 方法当物件的wait 方法被调用 目前的线程会被放入对象的等待池中 线程归还对象的锁定其它
17、的线程可竞争对象的锁定 wait notify 当物件的notify 被调用 它会从目前对象的等待池中通知 一个 线程加入回到锁定池的Blocked状态被通知的线程是随机的 被通知的线程会与其它线程共同竞争对象的锁定如果您呼叫notifyAll 则 所有 在等待池中的线程都会被通知回到锁定池的Blocked状态 wait notify 当线程呼叫到对象的wait 方法时 表示它要先让出对象的锁定并等待通知 或是等待一段指定的时间被通知或时间到时再与其它线程竞争对象的锁定如果取得锁定了 就从等待点开始执行 wait notify publicsynchronizedvoidsetProduct
18、intproduct if this product 1 try 目前店员没有空间收产品 请稍候 wait catch InterruptedExceptione e printStackTrace this product product System out printf 生产者设定 d n this product 通知等待区中的一个消费者可以继续工作了notify wait notify publicsynchronizedintgetProduct if this product 1 try 缺货了 请稍候 wait catch InterruptedExceptione e pri
19、ntStackTrace intp this product System out printf 消费者取走 d n this product this product 1 取走产品 1表示目前店员手上无产品 通知等待区中的一个生产者可以继续工作了notify returnp 容器类的线程安全 可以使用java util Collections的synchronizedXXX 等方法来传回一个同步化的容器对象使用Iterator遍访对象时 您仍必须实作同步化 Listlist Collections synchronizedList newArrayList Listlist Collecti
20、ons synchronizedList newArrayList synchronized list Iteratori list iterator while i hasNext foo i next ThreadLocal类别 尝试从另一个角度来思考多线程共享资源的问题共享资源这么困难 那么就干脆不要共享使用java lang ThreadLocal 为每个线程创造一个资源的复本 ThreadLocal类别 publicTget 取得目前执行get 方法的线程Threadcurrent Thread currentThread 根据线程取得线程自有的资源Tt storage get cu
21、rrent 如果还没有线程专用的资源空间 则建立一个新的空间if t null ThreadLocal类别 publicstaticSomeResourcegetResource 根据目前线程取得专属资源SomeResourceresource threadLocal get 如果没有取得目前专属资源if resource null 建立一个新的资源并存入ThreadLocal中resource newSomeResource threadLocal set resource returnresource BlockingQueue 如果BlockingQueue的内容为空 而有个线程试图从Q
22、ueue中取出元素 则该线程会被Block 直到Queue有元素时才解除Block如果BlockingQueue满了 而有个线程试图再把资料填入Queue中 则该线程会被Block 直到Queue中有元素被取走后解除Block BlockingQueue BlockingQueue ArrayBlockingQueue指定容量大小来建构LinkedBlockingQueue默认没有容量上限 但也可以指定容量上限PriorityBlockingQueue严格来说不是Queue 因为它是根据优先权 Priority 来移除元素 Callable与Future 可以协助您完成Future模式 Executors 可以使用Executors来建立线程池