多线程菜鸟进阶 一
QQ:158067568
作者:Legend
本文将进入多线程的学习中。在开始之前,需要明白线程的概念。
线程不是进程
作为有一定开发经验的程序员来说,在java中实现多线程是一件很容易的事情,你只需要将你的类继承Thread类或者实现Runnable接口就可以。其实线程完全可以理解为一个任务。可以同时运行多个任务的程序,就成为多线程程序。
然而线程并非进程。进程包括线程,每一个进程都拥有一套自己的变量,而线程间则共享这套变量。从而带来了很多风险,比如最典型的脏数据。这些以后会讨论。
线程状态
在java中,线程被定义成有6中状态:
NEW
至今尚未启动的线程处于这种状态。 即刚刚new出来的Thread,但是还未调用start()方法。
RUNNABLE
正在 Java 虚拟机中执行的线程处于这种状态。 该状态是调用了start()方法后的状态,出于该状态的线程不一定是正在运行的,他有线程调度器来决定是否运行。
BLOCKED
受阻塞并等待某个监视器锁的线程处于这种状态。 阻塞与等待不同,阻塞通常是得不到所需要的资源而被迫停下来等待。
WAITING
无限期地等待另一个线程来执行某一特定操作的线程处于这种状态。
TIMED_WAITING
等待另一个线程来执行取决于指定等待时间的操作的线程处于这种状态。
TERMINATED
已退出的线程处于这种状态。有两种情况会让线程退出,其一是run方法中的任务执行完成,其二是线程执行时出现异常。
java的线程状态只有如上6中,他们以enum形式被定义在Thread.State中。这里要说一下等待状态,有很多方式能够让线程进入等待状态,比如调用join()方法。
join()
对于这个方法,还是要特别的强调一下。在api中的解释如下:Blocks the current Thread (Thread.currentThread()
) until the receiver finishes its execution and dies.翻译过来就是:阻塞当前线程,然后让接受者完成任务之后,当前线程才开始继续执行任务。
但是如果接受者在被调用了join方法后,有被调用了interrupt()方法,则会抛出java.lang.InterruptedException异常。可以参考代码ThreadDemo01。
package cn.edu.heut.zcl;
public class ThreadDemo01 {
public static void main(String[] args) {
TA ta = new TA();
ta.start();
try {
ta.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
int i = 0;
while ((i++) < 10) {
System.out.println("-------");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TA extends Thread {
@Override
public void run() {
super.run();
int i = 0;
while ((i++) < 40) {
System.out.println("---->A");
if (i == 10) {
Thread.currentThread().interrupt();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
记住:join()方法是将当前线程阻塞
interrupt()与中断线程
开发时常常需要用到中断线程,在早期的java版本中,有stop()等方法用来控制线程生死,当时这些方法现在已经废弃,具体愿意以后会谈,同时亦可以参考sun的一片文章《Why Are Thread.stop, Thread.suspend, Thread.resume and Runtime.runFinalizersOnExit Deprecated?》网址如下:
http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
当然,jdk还是为我们提供了强化终止线程的方法。然而,interrupt方法只是可以用来请求终止线程。当对一个线程调用interrupt方法之后,线程的中断状态将被置位。每一个线程都具有一个中断状态,他是一个boolean标志。在实现自己的线程时,应该实时检查该标志,以判断线程是否被中断。
可以通过Thread.currentThread()方法得到当前线程,然后通过is isInterrupted()方法,来查看中断状态。通常如下实现:
while (!Thread.currentThread().isInterrupted() && 。。。) {}
如果你已经运行了ThreadDemo01代码,那么你会发现,在TA类中如下代码处:
if (i == 10) {
Thread.currentThread().interrupt();
}
将会抛出异常java.lang.InterruptedException。这个是由于在TA线程中调用了interrupt方法后,中断状态已经置为,如果此时再调用sleep等阻塞方法后,该线程不会休眠,想法,他将抛出中断异常并且将中断状态清楚。所以如下代码是不会让线程TB停止。CopyOfThreadDemo02
package cn.edu.heut.zcl;
public class CopyOfThreadDemo02 {
public static void main(String[] args) {
TB ta = new TB();
ta.start();
int i = 0;
while ((i++) < 10) {
System.out.println("-------");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TB extends Thread {
@Override
public void run() {
super.run();
int i = 0;
while (!Thread.currentThread().isInterrupted() && (i++) < 40) {
System.out.println("---->A");
if(i == 4) Thread.currentThread().interrupt();//在sleep之前调用,将不能终止线程
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//if(i == 4) Thread.currentThread().interrupt();//在sleep之后调用,将能终止线程
}
}
}
你可以自己试一试,运行如上代码,不能中断TB线程。但是如果在sleep之后调用interrupt,则会中断线程。
这两个方法看上去很像,作用也相似可以通过下表来比较两种异同。
|
是否是static
|
返回值
|
不同
|
interrupted
|
是
|
当前的中断状态
|
调用后改变中断状态
|
isInterrupted
|
否
|
不改变
|
谈优先级可能并不陌生,在java中,每一个线程都有一个优先级。默认情况下,一个线程的优先级直接继承自他的父类。sun将java的优先级分成10级,1表示最小优先级,10表示最高优先级。同时jdk中还定义了3个常量MIN_PRIORITY(1级)、MAX_PRIORITY(10级)、NORM_PRIORITY(5级)。
线程的优先级是依赖与平台的,windows中有7个优先级。而在Linux中,java虚拟机将线程的优先级忽略,即所有线程的优先级都一样。所以在编写程序是,尽量不要依赖于优先级。
setPriority()方法,顾名思义就是设置优先级的。
yield的中文意思是:屈服。其实理解成让步更加准确。调用该方法,将导致当前执行线程出于让步状态。如果此时有其他线程一起来抢夺cpu资源,那么只要这个抢夺的线程的优先级不低于调用线程。则抢夺线程将会被调用。
线程属性----守护线程
守护线程的用途就是为其他线程提供服务。当被服务者死亡后,其也就没有存在的价值,也就跟着去死了。设置守护线程很简单:
setDaemon(true)
只需一步,轻松搞定。在使用守护线程时需要记住,永远不要去访问固有资源,如文件、数据库等。以为你不知道什么时候守护线程会结束。
可以参考DeamonDemo:
package cn.edu.heut.zcl;
/**
* 演示守护线程
* @author Legend
*
*/
public class DeamonDemo {
public static void main(String[] args){
DemonRunnable dr = new DemonRunnable();
dr.setDaemon(true);//设置为守护线程
dr.start();
int i = 0 ;
while((i++)<10){
try {
Thread.sleep(500);
System.out.println(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static class DemonRunnable extends Thread{
@Override
public void run() {
super.run();
while(true){
System.out.println("------");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
分享到:
相关推荐
这本书对JAVA多线程进阶帮助非常之大而且详细、融会贯通、看了必定打通多线程任督二脉
多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个(进程)程序,尽管使得每个线程看起来在其执行过程都是歇歇停停。进程被操作系统互相隔开,因此不会彼此干涉,这使得用进程...
多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个(进程)程序,尽管使得每个线程看起来在其执行过程都是歇歇停停。进程被操作系统互相隔开,因此不会彼此干涉,这使得用进程...
Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据
java多线程PPT 多线程基本概念 创建线程的方式 线程的挂起与唤醒 多线程问题
多线程(共44页).ppt 推荐优质Java课程 疯狂Java语言编程 Java入门到进阶教程 17.网络编程(共42页).ppt 推荐优质Java课程 疯狂Java语言编程 Java入门到进阶教程 18.类加载与反射(共25页).ppt
一个java 多线程操作数据库应用程序!!!
这套课程既可以作为从零基础开始...课程的主要内容涉及有JAVA基础课程、JAVA多线程与并发编程、数据库开发基础和进阶、Spring Framework、Spring进阶、Spring MVC框架、Spring boot、Java常用类库、Java异常处理等等
详细的讲解了java多线程的原理,并配有代码进行实战,适合java初学者和想对多线程有进一步了解的人。
java多线程并发查询数据库,使用线程池控制分页,并发查询。
该文档总结了Java多线程相关的知识点,分享给大家,简单易懂!
java多线程处理数据库数据,使用并发包,无框架,可批量处数据库数据,进行增删改。。等等操作。
java多线程经典案例,线程同步、线程通信、线程阻塞等经典案例
多线程启动.java多线程启动.java多线程启动.java多线程启动.java
java多线程实现大批量数据切分成指定份数的数据,然后多线程处理入库或者导出,线程的个数和每份数据的数量都可以控制
Java多线程编程实战指南(核心篇) 高清pdf带目录 随着现代处理器的生产工艺从提升处理器主频频率转向多核化,即在一块芯片上集成多个处理器内核(Core),多核处理器(Multicore Processor)离我们越来越近了――如今...
JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载JAVA多线程端点续传下载...
java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号 java多线程模拟队列实现排队叫号,多线程模拟排队叫号取号
java多线程,对多线程,线程池进行封装,方便使用