在说线程之前,有必要说下线程与进程之间的关系。
附oracle官网链接:https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html
这里有原版的关于线程和进程的介绍,我们只简单介绍下,作为知识普及。
一.进程与线程的关系
1.进程:进程一般情况下是程序或者应用程序的同义词,是系统进行资源和调度的基本单位,是操作系统结构的基础。它有自己独立的内存空间,换句话说,它有一套私有的运行时资源。在现代面向线程的计算机结构中,进程作为了线程的容器存在,而进程变为了程序的代名词。但是要注意的是,Java虚拟机的大多数实现都是作为一个进程运行的。
2.线程:在面向线程的计算机结构中,线程有时被称为轻量级的进程。在进程中,各个线程共享进程的资源(内存和文件)。每个应用程序都至少包含一个线程。
3.为什么要使用线程进行并发程序设计?
因为相对于进程来说,线程的切换和调度的成本远远小于进程。
二.线程的生命周期
既然要说线程,就免不了说下线程的生命周期,也就是各个状态之间的转换。
可以看到,在源码Thread类中定义了一个枚举类型State,这个State就是线程生命周期中的各种状态。
根据英文注释,我们可以知道各个状态的含义,这里不细说。
附线程的状态转换图:
后续篇我们逐渐详述介绍这几种状态之间的转换过程。
三.线程的基本操作(这些都很简单,不在这里详细说)
1.新建线程
新建一个线程有两种方式:一种是继承Thread类,并重写Thread类的run方法(因为你要在run方法中实现你的业务逻辑);另外一种是实现Runnable接口。
public class ThreadDemo extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
System.out.println("继承Thread实现线程执行");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
new ThreadDemo().start();
}
}
public class RunnableDemo implements Runnable {
@Override
public void run() {
System.out.println("我的第一个线程程序!");
}
public static void main(String[] args) {
new Thread(new RunnableDemo()).start();
}
}
其实通过源码来看,实际就是一种方式,直接实现Runnable接口。我们可以看下Thread源码类中:
所以关于如何新建线程的方式的讨论可以休矣。
2.废弃方法(可以不看了)
stop方法:暴力终止,会出现数据不一致,废弃也在情理之中,被带有中断机制的方法代替了。
suspend:挂起方法,也被废弃了,是因为调用此方法后,线程挂起后不释放资源,并且线程的状态是RUNNABLE,可能会让我们误判当前的系统状态。
resume:是与suspend配套使用的,但是如果它比suspend先执行,那线程永远挂着了,图就不截了。
3.中断方法:
有关中断的有三个方法:
①Thread类中的interrupt()方法是实例方法,它可以设置线程的中断标识(也就是说并不是调用这个方法就中断了)
②配合Thread类中的实例方法isInterrupted()来判断当前调用线程是否设置了中断标识。
③Thread类中的interrupted()也是用来判断当前的中断状态,但是会清除中断标识位。
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().interrupted());
if(Thread.currentThread().isInterrupted()){
System.out.println("我被中断了!");
break;
}
}
}
};
t.start();
t.interrupt();
}
另外要注意的是,使用Thread.sleep(long xx)方法时(还有join方法,凡是报中断异常的方法),如果线程被中断,会抛出中断异常,并且标志位也会被清除。
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
@Override
public void run() {
while(true){
try {
System.out.println(Thread.currentThread().getName()+"|"+Thread.currentThread().isInterrupted());
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+"|"+Thread.currentThread().isInterrupted());
} catch (InterruptedException e) {
e.printStackTrace();
//如果要正确处理逻辑,这里要恢复中断标志位,重新进行中断
//重新设置中断标志
Thread.currentThread().interrupt();
}
if(Thread.currentThread().isInterrupted()){
System.out.println("我被中断了!");
break;
}
}
}
};
t.start();
t.interrupt();
}
4.等待(wait)和通知(notify)
首先要知道,这两方法是Object类中的方法,也就是说任何类都继承了这两方法。
在一个线程中,当一个对象调用wait()方法后,当前线程就会等待在这个对象上。直到另外一个线程调用了obj.notify()方法后,才能解除等待。要注意的第一点,这里的对象是同一个!第二点,这个对象必须被用作监视器锁!第三点,等待的线程必须获得了监视器锁后才能执行,并不是说另一个线程执行了notify()方法后就能被唤醒了!
public class WaitNotifyDemo{
final static Object obj = new Object();
static class T1 extends Thread {
@Override
public void run() {
synchronized (obj) {
System.out.println(System.currentTimeMillis()+":T1 start!");
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+":T1 end!");
}
}
}
static class T2 extends Thread {
@Override
public void run() {
synchronized (obj) {
System.out.println(System.currentTimeMillis()+":T2 start!");
obj.notify();
try {
Thread.sleep(2000);//为了看的明显,等待2s
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+":T2 end!");
}
}
}
public static void main(String[] args) {
new T1().start();
new T2().start();
}
}
5.线程的加入(join)和谦让(yield)
线程的加入:在一个线程A中调用线程B的join()方法,那么线程A就必须等线程B的逻辑执行完成后,才能继续往下执行自己A的逻辑。加入实际就是一起走的意思!下面例子,最后i肯定是100000.
public class ThreadJoinDemo{
public volatile static int i = 0;
static class T1 extends Thread {
@Override
public void run() {
for(i=0;i<100000;i++);
}
}
public static void main(String[] args) throws InterruptedException {
T1 t1 = new T1();
t1.start();
t1.join();
System.out.println(i);
}
}
线程资源让出-yield:Thread.yield()是一个静态的本地方法。让出的意思很明确,让出CPU资源。但是,让出了我还要争夺的!
四.线程的分类管理
1.线程的分组-线程组
给线程分个组,起个好听的名字吧,方便管理,默认新建的线程所在的线程组是创建线程的父组。
public class ThreadGroupDemo implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadGroup tg = new ThreadGroup("zhaodf");
Thread t1 = new Thread(tg, new ThreadGroupDemo(), "T1");
Thread t2 = new Thread(tg, new ThreadGroupDemo(), "T2");
Thread t3 = new Thread(new ThreadGroupDemo());
t1.start();
t2.start();
t3.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getThreadGroup().getName()+"_"+Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.守护线程:守护线程守护的是谁?守护的是用户线程,用户线程不存在了,它就没有意义了,因此也就停掉了。
public class Daemon {
public static class DaemonT extends Thread{
@Override
public void run() {
while(true){
System.out.println(System.currentTimeMillis()+"_"+Thread.currentThread().getName()+"_i am alive");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
Thread t = new DaemonT();
//必须在start方法之前设置守护线程,这样t变为守护线程,而主线程main成为用户线程。当主线程休眠2秒后,守护线程也退出
//如果放在start之后,会抛出Exception in thread "main" java.lang.IllegalThreadStateException异常
t.setDaemon(true);
t.start();
System.out.println(System.currentTimeMillis()+"_"+"主线程名称:"+Thread.currentThread().getName());
Thread.sleep(2000);
}
}
3.线程的优先级:
线程的优先级并不能保证线程优先执行,这点要注意。
public class PriorityDemo{
public static class HightPriority extends Thread{
static int count = 0;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized (PriorityDemo.class) {
count++;
if(count>10000){
System.out.println("HightPriority is complete");
break;
}
}
}
}
}
public static class LowerPriority extends Thread{
static int count = 0;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized (PriorityDemo.class) {
count++;
if(count>10000){
System.out.println("LowerPriority is complete");
break;
}
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread high = new HightPriority();
Thread low = new LowerPriority();
//设置优先级并不能保证线程一定优先执行
high.setPriority(Thread.MAX_PRIORITY);
low.setPriority(Thread.MIN_PRIORITY);
high.start();
low.start();
}
}
- 大小: 34.8 KB
- 大小: 30.8 KB
- 大小: 33 KB
- 大小: 15.1 KB
- 大小: 3.8 KB
- 大小: 26.7 KB
分享到:
相关推荐
并发库高级应用\多线程\Java
在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...
Java 多线程与并发理论基础 Java 多线程与并发是 Java 编程语言中的一种机制,用于提高程序的执行效率和响应速度。多线程的出现是为了解决 CPU、内存、I/O 设备速度差异的问题,通过分时复用 CPU、缓存和进程、...
Java多线程实战精讲是Java开发者必备的技能之一,特别是在处理高并发场景时,它的重要性不言而喻。本文将深入探讨Java多线程的相关知识点,帮助你全面理解并掌握这一核心概念。 1. **线程基础** - **线程定义**:...
综上所述,《Java多线程与高并发入门到精通》是一门全面涵盖Java多线程编程基础及高级技术的课程。无论您是初学者还是有一定基础的开发者,都能够从中获得宝贵的知识和经验。通过学习这门课程,您将能够掌握多线程的...
《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...
java多线程与高并发java多线程与高并发java多线程与高并发
Java多线程与并发编程是Java语言中用于处理多任务执行的关键技术,它能够帮助开发者设计出能够有效应对高并发请求的应用程序。在现代的线上(Online)和离线(Offline)应用中,合理利用多线程技术可以大幅提高系统...
Java多线程与并发编程是Java开发中至关重要的一部分,它涉及到如何高效地利用CPU资源,以实现程序的并行执行。在操作系统层面,多任务和多进程是通过分配不同的内存空间来实现的,而线程则共享同一进程的内存,这...
Java多线程、并发以及线程池是Java编程中至关重要的概念,特别是在处理高并发、高性能的系统设计时。以下是对这些主题的详细说明: 1. **Java 程序中的多线程** - 多线程允许一个程序同时执行多个任务,提高程序...
在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多对并发特性的支持,例如:线程池。.......................................JAVA线程、线程池资料----下载不扣分,回帖加1分,欢迎下载,童叟无欺JAVA线程、...
Java多线程中,线程的生命周期是编程中必须理解的重要概念。在JDK1.5之前,线程被划分为五个状态,分别是新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。在JDK1.5及之后,线程的...
在Java编程中,多线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而提高了系统的效率和响应性。然而,在某些场景下,我们可能需要控制线程的执行顺序,确保它们按照特定的顺序交替运行,这在并发编程...
《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...
在当今高度并发的应用环境中,Java多线程技术被广泛应用于处理数据库操作,以提升系统的响应速度和处理能力。本文将基于一个具体的Java多线程操作数据库的应用程序,深入探讨其背后的原理、实现细节以及潜在的挑战。...
本篇文章将深入探讨Java中的多线程并发机制,并通过具体的示例来帮助读者更好地理解和掌握这一重要概念。 #### 二、为什么需要多线程? 多线程技术的存在主要解决了计算机系统中资源利用率低下的问题。在没有多...
1. **线程基础**:书中首先介绍了Java中线程的基本概念,包括如何创建线程(通过继承Thread类或实现Runnable接口)、启动线程以及线程的生命周期状态(新建、运行、阻塞、等待、死亡)。 2. **线程同步**:为了解决...