`
春花秋月何时了
  • 浏览: 39982 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java线程概述及API一

 
阅读更多

1 创建线程与创建线程运行时代码

在Java中,创建线程的方式只有一种,就是创建Thread对象的实例。创建线程运行时代码有三种方式:

第一种:继承Thread类,覆写其run方法。

第二种:实现Runnable接口,实现run方法,Thread类也实现了Runable接口。

第三种:实现Callable接口,实现其call方法,这种方式是在JDK1.5中的java并发包中引入的。

 

start()方法与run()方法的区别

start()方法用于启动线程,start方法调用之后,线程进入可运行状态,一旦线程调度程序调度执行,线程即进入运行状态,线程启动后JVM才会给线程分配相应的资源,例如栈内存空间。然后回调线程运行时代码。

run()方法用于执行线程的运行时代码,如果直接调用该方法并没有创建新的线程而是在当前线程中被执行。

 
覆盖了Thread对象的run方法,同时传入一个Runnable的实现类?

我们知道线程创建完成之后,然后JVM回调线程运行时代码run(),所以查看Thread的默认run()实现:

 

/* What will be run. */
private Runnable target;
....
@Override
public void run() {
    if (target != null) {
        target.run();
    }
}

 

 其中target就是Runable对象,默认的run方法的逻辑是,如果传递了Runnable的实现类,就运行Runnable的run方法。故:当覆盖了Thread对象的run方法之后,执行的肯定是覆盖之后的逻辑,原来的这段逻辑如果不存在了,

就算传入了Runnable的实现类,也不会执行。

 

最后,Thread对象实现了Runnable接口(实现了run方法),而构造方法中又可以接受一个Runnable接口的实现类(也实现了run方法),称之为target,在执行的时候,如果target存在,就执行target的run方法。这实际上是装饰者设计模式(又称包装设计模式)

 

sleep()方法与wait()方法的区别

sleep()方法是Thread类中定义的静态方法,作用是让当前线程进行休眠暂停执行,在休眠期间线程不会请求CPU执行,因此其他线程(甚至更低优先级的线程)可以获得更多的运行机会。但是如果持有同步锁,并不会释放锁。

sleep方法有InterruptedException编译时异常需要捕获。并且不能指定休眠某一特定的线程t.sleep(),它只会是使当前线程被sleep 而不是t线程,所以即使t.sleep(...)这样调用,被暂停的也不是t线程而是当前线程,正确的用法应该是Thread.sleep(...)。调用sleep方法,线程进入到阻塞状态并不释放所占有的资源,sleep方法结束返回之后,线程重新回到可运行状态,而不是运行状态,需要线程调度机制重新恢复其到运行状态。

 

另外,java.util.concurrent.TimeUnit类的提供了语义更明确的sleep封装实现,其底层还是调用了Thread.sleep(...)方法,只是其单位更明确,例如休眠2秒钟:TimeUnit.SECONDS.sleep(2);

 

wait()方法是Object类中定义的方法,只能在同步方法或者同步代码块中调用,如果持有同步锁,会释放锁,让其他需要获得该锁的线程有机会运行。当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同)

wait方法同样也可以在wait期间因为被其他对象调用interrupt()方法二产生InterruptedException运行时异常。一旦一个对象调用了wait方法,必须要采用notify()和notifyAll()方法唤醒该进程。调用wait或者notify的时候,当前线程必须要是对象lock的拥有者,否则会抛出IllegalMonitorStateException异常。

synchronized (share) {
   share.wait();
}

 当线程在synchronized中调用了share.wait()时,在放弃了CPU的同时,也放弃了share这个对象的lock,进入这个对象的wait pool。

当另外一个线程调用了share.notify()时,将从wait pool中拿出一个线程,让该线程获得lock,并进入可运行状态,等待线程调度执行。

这也就是为什么wait/notify需要加锁的原因。

 

5 线程挂起与恢复suspend/resume

suspend可以将正在执行的线程挂起暂停执行。resume即使线程从挂起状态恢复。但这两个 API 是过期的,也就是不建议使用的。因为suspend()方法在执行时不会释放线程占用的资源(比如同步锁),并且没有超时时间的设定,如果resume在suspend之前调用或者在同步块内部执行,并且同步锁已经被挂起的线程占用,那么将陷入死锁状态。对于被挂起的线程,使用jconsole查看它的线程状态居然还是 Runnable。

 

另外,System.out.println(...)也是一个同步方法, 在执行打印之前需要获取PrintStream对象锁。并且PrintStream的实例对象out是System类的一个静态实例,System类中只有唯一的一个PrintOut对象:

public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
}

 

 所以下面的代码将永远无法打印出main end!,因为挂起的thread线程占用了PrintStream对象锁---out.

public class MyThread extends Thread{
	private long i = 0;
	
    @Override
    public void run() {
        while (true) {
            i++;
            System.out.println(i);//同步方法
        }
    }
    
    public static void main(String[] args) throws Exception{
    	MyThread thread = new MyThread();
    	
    	thread.start();//启动一个线程'thread'
    	
    	Thread.sleep(1000l);//使当前线程(main线程)睡眠
    	
    	thread.suspend();//挂起线程'thread'
    	
    	System.out.println("main end!");
	}
}
分享到:
评论

相关推荐

    java 多线程设计模式 进程详解

    第二章 Java线程API 通过Thread类创建线程 使用Runable接口的线程 线程的生命周期 线程命名 访问线程 线程的启动、停止和连接 总结 第三章 同步技术 银行的例子 异步读取数据 一个进行同步操作的类 同步块 嵌套锁...

    JAVA_API1.6文档(中文)

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I...

    Java 1.6 API 中文 New

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/...

    JavaAPI1.6中文chm文档 part1

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I...

    java api最新7.0

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/...

    Java程序设计基础:Java语言概述.pptx

    1996年1月,Java的第一个开发包JDK1.0发布。 Java历史网站 Java语言特点 Java极其流行,其设计特性:“一次编译,到处运行”。 简单性(simple) 面向对象(object oriented) 分布式(distributed) 解释型...

    RexCrawler:一个极简的 Java 多线程爬虫 API

    一个用于 Java 的简约多线程爬虫 API。 分散其简约的结构,此爬虫基于 Java ForkJoin 框架,该框架允许 RexCrawler 通过将其本地工作负载分区来按需创建其他守护进程。 这种方法的一个关键好处是更好地控制粒度和更...

    (超赞)JAVA精华之--深入JAVA API

    1.6 Java线程 1.7 Java 5.0多线程编程 1.8 Java Socket编程 1.9 Java的内存泄漏 1.10 抽象类与接口的区别 1.11 Java变量类型间的相互转换 2 JAVA与WEB 2.1 JMX规范 2.1.1 JMX概述 2.1.2 设备层(Instrumentation ...

    java jdk-api-1.6 中文 chmd

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I...

    JavaAPI中文chm文档 part2

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I...

    编写多线程的 Java 应用程序

    Java Thread API 允许程序员编写具有多处理机制优点的应用程序,在后台处理任务的同时保持用户所需的交互感。Alex Roetter 介绍了 Java Thread API,并概述多线程可能引起的问题以及常见问题的解决方案。

    Java基础知识点总结.docx

    一、 Java概述 3 二、 Java语法基础 5 数据类型 5 运算符号 14 语句 15 函数 15 方法重载(Overloadjing)与重写(Overriding) 16 数组 17 总结 18 三、 常见关键字 20 四、 面向对象★★★★★ 21 五、 封装(面向...

    Java语言基础 Java网络编程技术 Java程序设计使用教程 第10章 网络通信(共53页).ppt

    Java语言基础 Java网络编程技术 Java程序设计使用教程 第01章 java语言概述(共43页).ppt Java语言基础 Java网络编程技术 Java程序设计使用教程 第02章 java语言基础(共112页).ppt Java语言基础 Java网络编程技术...

    [Java参考文档].JDK_API 1.6

    javax.imageio.spi 包含用于 reader、writer、transcoder 和流的插件接口以及一个运行时注册表的 Java Image I/O API 包。 javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/...

    Java语言基础 Java网络编程技术 Java程序设计使用教程 全套PPT课件资源 共10个章节 含全部源代码.rar

    【完整课程列表】Java语言基础 Java网络编程技术 Java程序设计使用教程 第01章 java语言概述(共43页).pptJava语言基础 Java网络编程技术 Java程序设计使用教程 第02章 java语言基础(共112页).pptJava语言基础 ...

    JAVA SE学习精华集锦

    1.6 Java线程 60 1.7 Java 5.0多线程编程 65 1.8 Java Socket编程 80 1.9 Java的内存泄漏 85 1.10 抽象类与接口的区别 86 1.11 Java变量类型间的相互转换 87 2 JAVA与WEB 87 2.1 JMX规范 87 2.1.1 JMX概述 87 2.1.2 ...

Global site tag (gtag.js) - Google Analytics