本文主要总结多线程的问题。
Thread.currentThread().getName() 返回当前线程的名称
new Thread().Start() 线程开始执行
4.1.1 多线程的使用
若创建多线程,则需创建Thread的子类,并在对应的子类中的run()方法中写对应代码。
启动一个新的线程,需调用子类的start()方法。
需通过run方法的循环条件控制线程的结束。
4.1.2 后台线程与联合线程
setDaemon(true) 为后台线程
setDaemon(false)为前台线程
如果还有一个前台线程在运行,那么这个进程就不会技术。
如果只有前台线程技术,那么这个进程会结束。
如何合并线程,将一个线程合并到另外一个线程当中.join()方法,如设置合并线程时长,则为 join(毫秒值),具体可以查看jdk文档。
实现Runnable接口也可是实现多线程。
那么实现Runnable接口和join()方法两种产生多线程的区别:
继承Thread方式——实例化多次对象实际仍旧是一个对象,只能创建一个类的对象,不能创建多个。所以用这个方式不何时。
采用实现Runnable接口的对象——可以实例化多次这个对象,进行多线程。(适合多个线程的程序处理一资源的情况)避免单继承的情况局限性。都采用Runnable接口!
4.1.3 多线程在实际情况的应用。
网络聊天的程序的收发、数据库中表记复制的中途取消、www服务器为每个来访者都创建专线服务。
4.1.4多线程的同步问题(多线程的安全问题)
线程暂停方法Thread.sleep(毫秒值) 该方法会抛出异常
设置程序中不允许有两个或多个线程执行这段代码,即设置同步语句块实现独木桥效果,即同一时刻内只允许有一段线程进这段代码。
String str = new String("")
synchronized(this)
{
代码内容
}
声明的str为标志位(锁其标),str的值为1的时候才可以执行,为0的时候不可以执行,其他进程在等待。
方法前面声明了synchronized(同步函数),则该方法也会受到监视。
让代码块和函数使用同一个监视器,即可实现同步。
若想使用代码块和函数结合的方式实现同步,那么即判if(str.equals("method")){函数调用}else{代码块调用},代码块检查的同步对象为this。
线程的死锁的问题:
产生原因:如果多个线程的数据,共享程序数据,即多线程代码访问同一部分代码。线程进入了不同的监视器当中,互相的线程等不到对方的监视器。破坏了数据的一致性。
特征:程序停止不前。
4.1.5 线程间的通信、线程的等待和呼叫唤醒
两个线程,第一个线程中的代码刚结束,在第二个线程未开时执行前,第一个线程的代码又继续执行。
wait():当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器后,并调用notify(),
notifyall()唤醒所有
引用一段摘自百度知道的:
使用wait方法和使用synchornized来分配cpu时间是有本质区别的。wait会释放锁,synchornized不释放锁。
还有:(wait/notify/notifyAll)只能在取得对象锁的时候才能调用。
调用notifyAll通知所有线程继续执行,只能有一个线程在执行其余的线程在等待(因为在所有线程被唤醒的时候在synchornized块中)。这时的等待和调用notifyAll前的等待是不一样的。
notifyAll前:在对象上休息区内休息
notifyAll后:在排队等待获得对象锁。
notify和notifyAll都是把某个对象上休息区内的线程唤醒,notify只能唤醒一个,但究竟是哪一个不能确定,而notifyAll则唤醒这个对象上的休息室中所有的线程.
一般有为了安全性,我们在绝对多数时候应该使用notifiAll(),除非你明确知道只唤醒其中的一个线程.
至于有些书上说“notify:唤醒同一对象监视器中调用wait的第一个线程”我认为是没有根据的因为sun公司是这样说的“The choice is arbitrary and occurs at the discretion of the implementation.”
4.1.7 线程生命的控制
线程的生命周期分为:新建、就绪、运行、阻塞、死亡。
新建:当线程对象调用了start方法以后,线程就处于就绪状态,JAVA虚拟机会为其创建方法调用栈和程序计数器,处于这个状态的线程并没有运 行,他只是表示他可以运行而已。启动线程试用Start方法,而不是RUN方法,调用start方法来启动线程,系统会吧该RUN方法当成线程执行体来处 理,但如果直接调用线程对象的RUN方法,则RUN方法会被立即执行,而且在RUN方法之前的其他线程无法并行执行。
运行状态:当线程处于就绪状态获得CPU,就开始执行RUN方法,程序进入运行状态。一条线程开始运行以后,不可能一只处于运行状态,线程运行状态过程中也会被中断,目的是给其他线程获得执行的机会。系统会给每个可执行的线程一小段时间来处理任务。
阻塞状态:当发生如下情况,线程会进入阻塞状态:
1。线程调用SLEEP方法主动放弃所占用的资源。
2。线程调用了一个阻塞式IO方法,在改方法返回以前,该线程阻塞。
3。线程试图获得一个同步监视器,但该同步监视器正被别的线程所持有。
3。线程在等待某个通知。
4。线程调用了SUSPEND方法将该线程挂起。
死亡:
1。线程的RUN方法执行完成,线程正常结束。
2。线程抛出一个未捕获的EXCEPTION或ERROR。
3。直接调用线程的STOP方法来结束该线程。
为了测试某线程是否已经死亡,可以调用线程的isAlive()方法,当线程处于就绪,运行,阻塞的时候返回TRUE,当线程处于新建和死亡状态,该方法返回FALSE。
当对已经死亡的线程调用START方法,会抛出illegalThreadStateException异常。