java线程整理(一)
线程与进程的概念
进程就是在某种程度上相互隔离的、独立运行的程序,拥有并分配系统资源。
线程(thread),有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。
线程在程序中是独立的、并发的执行路径,每个线程有它自己的堆栈、自己的程序计数器和自己的局部变量。但它们它们共享内存、文件句柄和每个进程应有的状态。
一个进程中可以包含若干个线程。
为什么使用线程
线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统内多个程序间并发执行的程度,从而显著提高系统资源的利用率和吞吐量。
· 利用多处理器系统
· 简化建模
· 执行异步或后台处理
Java线程的常用的API
建议使用的方法
方法
|
说明
|
start
|
start()方法就是启动线程的方法,这个方法是线程类中最核心的方法。当调用这个方法以后,它就会启动线程,并让线程去执行指定的方法,而这里说的“指定的方法”,就是下个要说的run()方法。如果这个线程已经开始执行,再次调用该方法,则会抛出IllegalThreadStateException异常。
|
run
|
start()方法会将它作为线程的起点,线程执行的业务逻辑应该在这里实现。
并且run() 的访问控制符必须是public,返回值必须是void,run()不带参数。
|
sleep
|
sleep()方法是一个静态方法,让当前线程挂起。如果当前线程已经被别的线程中断的话,将会抛出InterruptedException异常,而且interrupted标志也会被清空。
|
join
|
保证当前线程停止执行,直到该线程所加入的线程完成为止。如果当前线程已经被别的线程中断的话,将会抛出InterruptedException异常,而且interrupted标志也会被清空。
|
yield
|
yield()使当前线程临时的中断执行,并让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让
步的线程还有可能被线程调度程序再次选中。JAVA的线程模型实际上映射到操作系统的线程模型,所以对于不同的操作系统,这个方法的就有不同的意义。对于非抢占式Operating System,这个方法使得其他线程得到运行的机会,但是对于抢占式的OS,这个方法没有太多的意义。
|
wait
|
Wait方法和后边的两个方法都来自Object。这个方法的作用是让当前线程等待,直到被唤醒或者等待的时间结束。当前线程进入等待队列的时候,会放弃当前所有的资源,所以当前线程必须获得这些对象的Monitor,否则会扔出IllegalMonitorStateException。
|
notify
|
通知其他线程可以使用资源了。这个方法的使用要求很多,总之需要当前线程获得被调用的notify方法的对象的monitor。
|
notifyAll
|
除了通知所有的线程可以准备执行之外,跟上面的方法要求一样。但是只有一个线程会被选择然后执行,这个就跟优先级和其他状态有关系了。
|
interrupt
|
中断线程。
|
不建议使用的方法
方法
|
说明
|
stop
|
强制使当前的线程停止执行。实际上,作为开发人员我们会意识到,线程的复杂程度是没有边际的,而这个方法这样武断的停止一个线程,必然导致问题产生。也就是说,这个方法天生就有问题。比如说一个线程掌握了很多对象,并且改变了其中一些的状态,如果突然当前对象突然被停止,将会释放这些对象的monitor,这个时候被改变状态的对象就是被损坏的对象,其他线程再来操作的时候问题就出来了。替代的办法就是让当前线程正常结束,不使用这个方法。就是我们设置一些标志,如果这些标志满足的时候,我们结束线程。
|
suspend
|
这个方法天生就有导致死锁的可能。如果当前线程持有很多对象的锁,但是当他suspend的时候,这些锁是不会释放的,想想就知道应该什么可能会发生,所以这个方法应该尽量不用。这里我们有办法替代这个方法,其实根替代stop的方法差不多,就是用wait方法来实现挂起,而不是事实上的挂起。比如:
|
resume
|
很显然,这个方法和上面的方法是对应的,所以上面用了wait方法来替代,所以这边应该用notify这个方法或者notifyAll这个方法来替代。其实这边可以把上面的实现方式结合起来,实现一个可以安全stop和suspend的线程。这个在我的源码里有实现,但是不知道是不是对的。不过感觉原则应该没有问题,那就是设置标志来结束或者挂起线程,而不是使用这些过时的方法。
|
关键字
|
说明
|
volatile
|
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
|
synchronized
|
1)synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
2)无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁,而且同步方法很可能还会被其他线程的对象访问。
3)每个对象只有一个锁(lock)与之相关联。
4)实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
|
线程的周期
线程也有它完整的生命周期,线程的整个周期由线程的创建、线程的启动、线程的阻塞和线程的停止等部分组成。
一个线程有4种状态,任何一个线程肯定处于这4种状态中的一种。
(1)初始态又成创建状态(New):一个线程调用了new方法产生了一个线程对象之后,并在调用start方法之前的所处状态。此时系统不为它分配资源。在初始态中,只能调用start或stop方法,调用其他方法将抛出非法状态例外(IllegalThreadStateException)的异常。
(2)可执行状态(Runnable):执行了一个线程对象的start()方法后,线程就转到Runnable 状态。每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排程器启动它;也可能它已正在执行。注意,如果线程处于Runnable状态,它也有可能不在执行中,这是因为还有优先级和调度问题。
(3)阻塞状态(NonRunnable):线程处于NonRunnable状态,这是由两种可能性造成的:要么是因挂起而暂停的,要么是由于某些原因而阻塞的,例如包括等待IO请求的完成。如通过对一个线程调用wait()函数后,线程就进入阻塞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态。当一个线程处于阻塞状态时,系统排程器就会忽略它,不对它进行排程。当处于阻塞状态的线程重新回到可执行状态时,它有可能重新执行。
(4)退出(Done):当一个线程正常结束,它便处于退出状态。这有两种可能性,要么是线程的run()方法执行完毕,要么是调用了stop()方法。
线程状态的转换
表11-1 线程状态转换函数
方 法
|
描 述
|
有 效 状 态
|
目 的 状 态
|
start()
|
开始执行一个线程
|
New
|
Runnable
|
stop()
|
结束执行一个线程
|
New或Runnable
|
Done
|
sleep(long)
|
暂停一段时间,这个时间为给定的毫秒
|
Runnable
|
NonRunnable
|
sleep(long,int)
|
暂停片刻,可以精确到纳秒
|
Runnable
|
NonRunnable
|
suspend()
|
挂起执行
|
Runnable
|
NonRunnable
|
resume()
|
恢复执行
|
NonRunnable
|
Runnable
|
yield()
|
明确放弃执行
|
Runnable
|
Runnable
|
如何创建一个简单的线程
一种是继承Thread类
一种为实现Runnable 接口
两者都要重写run()方法。
/*
* 继承Thread的方式
*/
class testThread extends Thread {
public void run(){
//do somethings
}
public static void main( String args[] ){
testThread t = new testThread( );
t.start();
}
}
/*
* 实现Runnable 接口
*/
class testThread implements Runnable{
public void run(){
//do somethings
}
public static void main( String args[] ){
Runnable testThread =new testThread ();
Thread myThread=new Thread(testThread);
myThread.start();
}
}
分享到:
相关推荐
其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。我们都知道计算机有高速缓存...
Java线程是多任务编程中的核心概念,它允许程序同时执行多个不同的任务,极大地提高了程序的效率和响应性。在Java中,线程是通过`Thread`类或实现`Runnable`接口来创建的。本文将深入探讨Java线程的相关知识点,并...
Java线程让步是多线程编程中一个重要的概念,主要涉及到如何控制线程的执行顺序和资源分配。`yield()`方法是Java提供的一种线程让步的方式,它允许当前正在执行的线程暂停,将执行权短暂地让给其他等待的线程,特别...
Java线程中的`join()`方法是一个非常重要的同步工具,它允许一个线程(通常为主线程)等待另一个线程(子线程)执行完成后再继续执行。`join()`方法定义在`java.lang.Thread`类中,它使得多线程间的协作更加有序。 ...
以下是对Java线程相关知识点的详细说明: 1. **线程的创建与执行** - 创建线程有两种方式:继承`Thread`类或者实现`Runnable`接口。继承`Thread`直接重写`run()`方法,而实现`Runnable`接口则需要提供一个包含业务...
在Java编程语言中,多线程和同步是两个至关重要的概念,它们对于构建高效、可靠的并发应用程序至关重要。这里我们将深入探讨这两个主题,并结合源码分析,以帮助你更好地理解和掌握。 1. **Java多线程** Java多...
通过 Runnable 接口创建线程类是 Java 中另一种常见的线程创建方式。该方式需要定义 Runnable 接口的实现类,并重写该接口的 run() 方法,该 run() 方法的方法体同样是该线程的线程执行体。然后,创建 Runnable 实现...
Java多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个任务,提高系统的效率和响应性。在Java中,线程的管理涉及到线程组、异常处理等多个方面。下面我们将详细探讨这些知识点。 首先,线程组(Thread...
下面将基于这些信息,综合整理出与Java线程相关的知识点。 ### Java线程基础 1. **线程的概念**:在Java中,线程是程序执行流的最小单元,一个标准的Java应用程序至少有一个线程,即主线程(main thread)。Java中...
Java线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...
根据给定文件的信息,我们可以提炼出以下相关的Java线程知识点: ...以上内容是根据给定文件中的信息整理出的关于Java线程的相关知识点。通过对这些概念的理解和掌握,可以更好地理解和应用Java中的多线程技术。
Java多线程整理汇总思维导图
Java多线程知识点整理.pdf
Java+创建线程的例子源码整理
其次,多线程是Java中实现断点续传的另一个重要方面。多线程可以提高文件传输效率,特别是在下载大文件时,可以创建多个线程同时下载不同的部分。每个线程负责文件的一部分,当所有线程完成其任务后,再将各个部分...
Java多线程技术是Java编程中的重要组成部分,它允许程序同时执行多个任务,极大地提高了程序的效率和响应性。在Java中,多线程主要通过`Thread`类、实现`Runnable`接口或`Callable`接口以及使用`ExecutorService`...
6. **Java线程文档**: `java线程.doc`和`Java线程.pdf`可能详细介绍了线程的生命周期、状态转换、线程间的通信(例如wait()、notify()、notifyAll()方法)、死锁、活锁等问题,以及如何通过`Thread.sleep()`、`yield...
以下是根据题目内容整理的一些Java线程相关知识点: 1. **线程睡眠**:`Thread.sleep()`方法用于使当前线程进入睡眠状态,参数单位为毫秒。例如,`sleep(10000)`表示线程将休眠10秒。 2. **线程创建方式**:Java...
- Java多线程编程知识包括线程创建、线程同步、线程通信以及线程池的使用等方面。 - 并发编程的相关知识点,例如锁机制、原子操作、volatile关键字等,也是面试时经常被问到的内容。 这些知识点涵盖了Java面试中...