Java多线程技能

来源:互联网 发布:淘宝买k粉暗语 编辑:程序博客网 时间:2024/06/14 19:05

《Java多线程编程核心技术》PDF电子版下载:
http://download.csdn.net/detail/u013142781/9452683

《Java多线程编程核心技术》书中实例源码下载: 
http://download.csdn.net/detail/u013142781/9453047

掌握如下关键技术点:

  • 线程的启动
  • 如何使线程暂停
  • 如何使线程停止
  • 线程的优先级
  • 线程安全相关的问题

进程和多线程的概念及线程的优点

进程:进程是操作系统结构的基础;是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动;是程序在一个数据集合上运行的过程,她是系统进行资源分配和调度的一个独立单位.
线程:在进程中独立运行的子任务
线程的优点:可以最大限度的利用CPU的空闲时间来处理其他任务,系统的运行效率大大提高
原理:CPU在任务之间不停切换,由于切换的速度非常快,给使用者的感受就是这些任务似乎就是同时进行。使用多线程技术后,可以再同一时间内运行更多不同种类的任务。

使用多线程

  • 继承Thread类

使用继承Thread类的方式创建新线程时,最大的局限就是不支持多继承,因为Java语言的特点就是单根继承,所以为了支持多继承,完全可以实现Runnable接口的方式,一边实现一边继承。两种方式创建的线程在工作时的性质是一样的,没有本质的区别。
在使用多线程技术时,代码的运行结果与代码执行顺序或调用顺序是无关的
线程是一个子任务,CPU以不确定的方式,或者说以随机的时间来调用线程中的run方法
Thread.java类中的start()方法通知"线程规划器"此线程已经准备就绪,等待调用线程对象的run()方法。run()方法则是main主线程直接调用,并不交给"线程规划器"。
注意:执行start()方法的顺序不代表线程启动的顺序

  • 实现Runnable接口

如果欲创建的线程已经有一个父类了,这时就不能再继承自Thread类了,因为Java不支持多继承,所以需要实现Runnable接口来应对这样的情况

  • 实例变量与线程安全

自定义线程类中的实例变量针对其他线程可以有共享不共享之分.这在多个线程之间进行交互时是很重要的一个技术点.
数据共享的情况可能会产生"非线程安全"问题.
添加synchronized关键字可以在任意对象及方法上加锁,加锁的这段代码称为"互斥区"或"临界区",实现排队调用
"非线程安全":主要指多个线程对同一个对象中的同一个实例变量进行操作时会出现值被更改,值不同步的情况,进而影响程序的执行流程

  • 留意i--与System.out.println()的异常

虽然println()方法在内部是同步的,但是i--的操作却是在进入println()之前发生的,所有有发生非线程安全问题的概率

currentThread()方法

currentThread()方法可返回代码段正在被哪个线程调用的信息

isAlive()方法

isAlive方法的功能是判断当前的线程是否处于活动状态
活动状态:就是线程已经启动且尚未终止
线程处于正在运行或准备开始运行的状态就认为线程是”存活”的.

sleep()方法

sleep方法的作用是在指定的毫秒数内让当前”正在执行的线程”休眠(暂停执行),这个”正在执行的线程”是指this.currentThread()返回的线程

getId()方法

getId方()法的作用是取得线程唯一标示

停止线程

Java中有以下3种方法可以终止正在运行的线程
1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止
2.使用stop()方法强行终止线程,但是不推荐使用这个方法,因为stop和suspend及resume一样,都是作废过期的方法,使用它们可能产生不可预料的结果
3.使用interrupt方法中断线程

  • 停止不了的线程

调用interrupt()方法仅仅是在当前线程中打了一个停止的标记.并不是真的停止线程

  • 判断线程是否是停止状态

this.interruptd():测试当前线程是否已经中断,执行后具有将状态标志清除为false的功能 public static boolean interrupted()
this.isInterruptd():测试线程是否已经中断但不清楚状态标志 public boolean isInterrupted()

  • 能停止的线程--异常法

抛出异常停止后边的代码

  • 在沉睡中停止

在sleep状态下停止某一线程,会进入catch语句,并且清除状态值,是之变成false

  • 能停止的线程--暴力停止

使用stop()方法停止线程则是非常暴力的

  • 方法stop()与java.lang.ThreadDeath异常

调用stop方法时会抛出java.lang.ThreadDeath异常
方法stop()已经作废,因为如果强制让线程停止则可能使一些请理性的工作得不到完成,对锁定的对象进行了"解锁",导致数据得不到同步的处理,出现数据不一致的问题

  • 释放锁的不良后果

使用stop()释放锁将会给数据造成不一致性的结果,如果出现这样的情况,程序处理的数据就有可能遭到破坏,最终导致程序执行的流程错误,一定要特别注意

  • 使用return停止线程

将方法interrupt()与return结果使用也能实现停止线程的效果.
不过还是建议使用"抛异常"的方法来实现线程的停止,因为在catch块中可以对异常的信息进行相关的处理,而且使用异常流能更好,更方便地控制程序的运行流程,不至于代码中出现多个return造成污染

暂停线程

  • suspend与resume方法的使用

suspend()方法暂停线程,resume()方法恢复线程的执行

  • suspend与resume方法的缺点--独占

在使用suspend与resume方法时,如果使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象

  • suspend与resume方法的缺点--不同步

在使用suspend与resume方法时也容易出现因为线程的暂停二导致数据不同步的情况

yield方法

yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片

线程的优先级

CPU优先执行优先级较高的线程对象中的任务 "线程规划器" 
设置线程优先级使用serPriority()方法
线程优先级分为1~10这10个等级,如果小于1或者大于10则JDK抛出异常throw new IllegalArgumentException()
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;

  • 线程优先级的继承性

线程的优先级具有继承性,比如A线程启动B线程,则B线程的优先级与A是一样的

  • 线程具有规则性

高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完。
当线程优先级的等级差距很大时,谁先执行完和代码的调用顺序无关。

  • 优先级具有随机性

优先级较高的线程不一定每一次都先执行完

  • 看谁运行得快

优先级较高的线程运行速度较"快",

守护线程

在Java线程中有两种线程:用户线程,守护(Daemon)线程
守护线程
是一种特殊的线程,它的特性有陪伴的含义,当进程中不存在非守护线程,则守护线程自动销毁,如垃圾回收线程.
守护线程的作用:是为其他线程的运行提供便利服务,最典型的应用就是GC(垃圾回收器),它就是衣蛾很称职的守护者
原创粉丝点击