copy :http://blog.csdn.net/MyTroy/article/details/38360495
一、Java线程状态
start之后是进去就绪状态,等待CPU的调度,而不是立即进去运行状态。当run函数返回,线程就终止了。
二、Thread.sleep
谁调用Thread.sleep方法谁休息,自己进入阻塞状态。Thread.sleep方法属于线程自己控制自己的状态。如果线程在sleep之前拥有某个对象的锁,则它在sleep的时候还会抱着这把锁不放。
三、obj.interrupt
obj是线程对象,其它线程调用obj的interrupt方法,将会打断obj线程的睡眠,引发obj线程的异常。
obj.stop,其它线程调用obj的stop方法可以让obj线程直接退出,粗暴直接,不要轻易使用(可能会导致某些打开的资源来不及关闭线程就退出了)。
四、join合并线程
Thread t1=new Thread(Runnable r);
t1.start();
t1.join(); //当前线程阻塞在此处
正在执行的线程调用t1的join方法将会合并t1线程,即相当于当前线程在方法调用(当前线程阻塞),直到等到t1线程执行完毕,当前线程才会继续执行。
yield:当前在执行的线程让出一次CPU时间给其它线程执行,自己立即进入就绪状态,等待CPU的再次调用。
(Thread.yield()谁调用此方法谁就让出CPU时间,但并不能保证让出后其它线程可以抢占到CPU时间。)
threadObj.setDaemon()方法将该线程标记为守护线程或用户线程,当正在运行的线程都是守护线程时,JVM会退出(该方法必须在线程启动前调用)。
五、synchronized互斥锁
每个对象只有一把锁(每一个对象对应一把锁),多个线程获取同一把锁时才会产生互斥效果,多个线程获取不同的锁时不会产生互斥效果。synchronized互斥锁锁住的是对象而不是代码。
六、死锁
所谓死锁: 是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称程序处于死锁状态或程序产生了死锁,这些永远在互相等待的线程称为死锁线程。 由于资源占用是互斥的,当某个线程锁住某个资源后,使得有关线程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象:死锁。
假设有两个线程a和b,线程a和b结束的条件是分别同时锁住obj1和obj2对象,如果a已经获取到了obj1的锁正在努力获取obj2的锁但是obj2的锁已经被b获取,同时b也正在努力获取obj1的锁,因为只有线程结束才能释放锁,而正常结束的条件是一个线程必须同时获取到两个锁,因此a和b都得不到另外一个锁都无法结束,陷入了永久的等待状态,此时程序产生死锁。
死锁程序例如:
- import java.util.logging.Level;
- import java.util.logging.Logger;
- public class DiedSynchronized {
- public static void main(String[] args) {
- Tellme m=new Tellme();
- Thread t1=new Thread(m,"t1");
- Thread t2=new Thread(m,"t2");
- System.out.println(Thread.currentThread().getName()+":t1和t2线程已经启动……");
- t1.start();
- t2.start();
- try {
- Thread.sleep((long)10000);
- } catch (InterruptedException ex) { }
- if(t1.isAlive() && t2.isAlive()) {
- System.out.println(Thread.currentThread().getName()+":10s内,t1和t2线程均没有正常结束,证明t1和t2线程死锁!");
- System.exit(0);
- }
- else
- System.out.println(Thread.currentThread().getName()+":t1和t2线程已经结束,证明没有死锁!");
- }
- }
- class Tellme implements Runnable {
- private Integer _number = new Integer(100);
- public boolean _flag = true;
- public void run() {
- if(_flag) {
- _flag=false;
- synchronized(this) {
- System.out.println(Thread.currentThread().getName()+":已经获取到this锁,正在获取Number锁……");
- try {
- Thread.sleep((long)1000);
- } catch (InterruptedException ex) { }
- synchronized(_number) {
- System.out.println(Thread.currentThread().getName()+":this锁和Number锁同时获取完毕!");
- }
- }
- }else {
- synchronized(_number) {
- System.out.println(Thread.currentThread().getName()+":已经获取到Number锁,正在获取this锁……");
- try {
- Thread.sleep((long)1000);
- } catch (InterruptedException ex) { }
- synchronized(this) {
- System.out.println(Thread.currentThread().getName()+":this锁和Number锁同时获取完毕!");
- }
- }
- }
- }
- }
运行结果如下:
run:
main:t1和t2线程已经启动……
t2:已经获取到Number锁,正在获取this锁……
t1:已经获取到this锁,正在获取Number锁……
main:10s内,t1和t2线程均没有正常结束,证明t1和t2线程死锁!
成功构建 (总时间: 10 秒)
t1和t2线程分别拥有this锁和Number锁,同时努力获取对方的锁,造成最终谁也得不到,程序进入死锁状态。Thread.sleep((long)1000)只是起放大作用,即使没有睡眠1秒程序也有可能进入死锁状态。
七、wait、notify、notifyAll
线程可以在任意对象的监视器(锁)上阻塞(wait,前提是获取到该对象的锁),也可以在唤醒任意一个wait在某个对象的监视器上的线程(notify,前提是获取到该对象的锁)。“获取到某个对象的锁”,就像获取到某种资格一样,只有有了这种资格才能够让自己阻塞在该锁上面或者唤醒已经阻塞在该锁上的其它线程。由此可知,每个对象的监视器上面自愿wait和被notify的线程只和该对象有关。因为每个对象都具有锁,每个锁均不同,故wait和notify的方法调用要通过对象调用,所以wait和notify方法要在Object中声明。
- import java.util.Random;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- /**
- * Producer_Customer Program for testing wait_notify_notifyAll
- *
- * @author 忘川
- */
- public class Producer_Customer {
- public static void main(String[] args) {
- Basket basket = new Basket();
- Producer pro = new Producer(basket);
- Customer cus = new Customer(basket);
- Thread proth1 = new Thread(pro, "一");
- Thread proth2 = new Thread(pro, "二");
- Thread proth3 = new Thread(pro, "三");
- Thread proth4 = new Thread(pro, "四");
- Thread custh1 = new Thread(cus, "custh1");
- Thread custh2 = new Thread(cus, "custh2");
- proth1.start();
- proth2.start();
- proth3.start();
- proth4.start();
- custh1.start();
- custh2.start();
- }
- }
- class Producer implements Runnable {
- private Basket basket = null;
- public Producer(Basket basket) {
- this.basket = basket;
- }
- public void run() {
- Random r = new Random();
- for (int i = 0; i < 4; i++) {
- basket.put(new Apple(Thread.currentThread().getName() + "#" + i));
- try {
- Thread.sleep((long) r.nextDouble() * 1000);
- } catch (InterruptedException ex) { }
- }
- }
- }
- class Customer implements Runnable {
- private Basket basket = null;
- public Customer(Basket basket) {
- this.basket = basket;
- }
- public void run() {
- Random r = new Random();
- for (int i = 0; i < 8; i++) {
- basket.eat();
- try {
- Thread.sleep((long) r.nextDouble() * 1000);
- } catch (InterruptedException ex) { }
- }
- }
- }
- class Basket {
- private Apple[] basket = new Apple[3];
- private int index = 0;
- public synchronized void put(Apple a) {
- while (index == 2) {
- try {
- this.wait();
- } catch (InterruptedException ex) { }
- }
- this.notifyAll();
- basket[index++] = a;
- System.out.println("生产:" + a + " 篮子剩余=" + index);
- }
- public synchronized void eat() {
- while (index == 0) {
- try {
- this.wait();
- } catch (InterruptedException ex) { }
- }
- this.notifyAll();
- System.out.println("吃掉:" + basket[--index] + " 篮子剩余=" + index);
- }
- }
- class Apple {
- public String ID;
- public Apple(String id) {
- this.ID = id;
- }
- public String toString() {
- return ID;
- }
- }
其中的一个运行结果如下:
run:
生产:三#0 篮子剩余=1
生产:四#0 篮子剩余=2
生产:一#0 篮子剩余=3
吃掉:一#0 篮子剩余=2
生产:二#0 篮子剩余=3
吃掉:二#0 篮子剩余=2
生产:三#1 篮子剩余=3
吃掉:三#1 篮子剩余=2
生产:一#1 篮子剩余=3
吃掉:一#1 篮子剩余=2
生产:一#2 篮子剩余=3
吃掉:一#2 篮子剩余=2
吃掉:四#0 篮子剩余=1
生产:二#1 篮子剩余=2
生产:三#2 篮子剩余=3
吃掉:三#2 篮子剩余=2
生产:二#2 篮子剩余=3
吃掉:二#2 篮子剩余=2
生产:二#3 篮子剩余=3
吃掉:二#3 篮子剩余=2
生产:三#3 篮子剩余=3
吃掉:三#3 篮子剩余=2
吃掉:二#1 篮子剩余=1
生产:四#1 篮子剩余=2
生产:一#3 篮子剩余=3
吃掉:一#3 篮子剩余=2
生产:四#2 篮子剩余=3
吃掉:四#2 篮子剩余=2
生产:四#3 篮子剩余=3
吃掉:四#3 篮子剩余=2
吃掉:四#1 篮子剩余=1
吃掉:三#0 篮子剩余=0
成功构建 (总时间: 0 秒)
从运行结果可以看出,每当篮子中苹果个数达到3个(篮子所能容纳的上线时),生产者线程就自愿wait在篮子的监视器上,转而让消费者线程先消费之后再唤醒生产者线程;每当篮子中的苹果个数为0时,消费者线程就会自愿wait在篮子的监视器上,转而让生产者线程先生产之后再唤醒消费者线程。篮子就像一个控制中心,生产过剩,生产线程就资源wait,转而让消费线程消费;反之亦然。
相关推荐
1. SpringBoot 自定义线程池以及多线程间的异步调用(@Async、@EnableAsync) 2.Java多线程之定时任务 以及 SpringBoot多线程实现定时任务 3.@EnableScheduling 与 @Scheduled
总之,基于任务的线程处理是Java并发编程的重要组成部分,理解并熟练掌握线程、任务、队列以及相关的调度工具,能帮助开发者编写出更高效、更稳定的并发程序。通过实践和学习提供的代码示例,你可以更好地理解这些...
《易语言源码多线程多任务下载软件》是一款基于易语言编程的高效下载工具,其核心特性在于利用多线程技术实现多个文件的同时下载,提高下载效率,满足用户快速批量下载的需求。本文将深入探讨易语言编程环境、多线程...
在这个“多线程多任务下载软件.zip”压缩包中,包含的是一个易语言项目的源码,可以作为学习和参考的实例。下面将详细解释多线程和多任务下载的概念,以及如何在易语言中实现这些功能。 1. **多线程技术**:在...
在易语言中,我们可以通过创建线程对象并调用其相关函数来实现这一功能。 1. **线程创建与启动**:在易语言中,创建线程通常涉及到“创建线程”和“启动线程”两个步骤。首先,我们需要定义一个子程序,这个子程序...
在Java开发中,Spring框架是广泛使用的,它不仅提供了丰富的功能,还支持诸如定时任务和多线程等高级特性。本示例将深入探讨如何在Spring框架中利用定时任务(Spring Task)启动多线程来执行并发操作。 首先,我们...
第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程第二章多任务和多线程...
本文将深入探讨多线程并发执行任务的相关知识点,并基于提供的`MyThread.java`文件,来分析和理解如何在Java中实现多线程。 首先,我们需要了解什么是线程。线程是操作系统分配处理器时间的基本单元,一个进程可以...
线程池是一种线程管理机制,它预先创建一组线程,当有任务需要执行时,线程池会自动分配一个空闲线程来执行任务,完成后再返回线程池。这种方式减少了线程创建和销毁的开销,提高了程序的运行效率。`QThreadPool`类...
12.如何实现多线程多任务?(Visual C++编程 源代码)12.如何实现多线程多任务?(Visual C++编程 源代码)12.如何实现多线程多任务?(Visual C++编程 源代码)12.如何实现多线程多任务?(Visual C++编程 源代码)...
在本文中,我们将深入探讨如何在Winform应用程序中实现多线程和多任务管理,这对于提高应用程序的性能和响应性至关重要,特别是处理耗时操作时。 首先,了解多线程的概念是必要的。在单线程应用程序中,所有任务都...
在.NET框架中,`System.Threading`命名空间提供了线程相关的类,如`Thread`、`ThreadPool`和`Task`等。`Thread`类是线程的基本表示,可以创建新的线程实例来执行特定的代码块。然而,直接使用`Thread`对象创建大量...
主要实现了,多个线程任务在同时执行的情况下,保证线程任务顺序的问题。更通俗来说,就是保证Thread1一定在thread2,thread3之后才能执行。另外,代码里我写了详细的注释,和测试的效果,绝对让你能看懂。还有我传的...
在WIN-TC下的基于线程的多任务系统实现
在计算机科学中,多线程是一种程序设计技术,它允许应用程序同时执行多个不同的任务或子任务,从而提高系统的效率和响应速度。多线程在Java、C++、Python等编程语言中都有广泛的应用。本篇文章将深入探讨多线程执行...
Qt是一个跨平台的C++库,提供了丰富的功能,包括对多线程的支持,这使得开发人员可以利用多线程来实现并发任务,如多任务下载。本示例"qt利用线程实现多任务下载"就是一个很好的实践,它不仅展示了Qt的多线程技术,...
在易语言中,多线程任务分配模块是实现并发处理的关键组件,尤其适用于处理耗时操作或者提高程序执行效率。本模块的源码提供了一个简单而实用的多线程解决方案。 首先,我们要理解什么是多线程。在计算机科学中,...
标题中的“多任务多线程下载器源码”是指一个软件程序,它的功能是同时处理多个下载任务,并且每个任务都是在独立的线程中运行。这种设计模式提高了下载效率,因为不同任务可以在CPU的不同核心上并发执行,避免了单...
Java多线程机制是Java编程中至关重要的一部分,它允许程序同时执行多个任务,提升应用程序的效率和响应性。以下是对各个知识点的详细说明: 9.1 Java中的线程: Java程序中的线程是在操作系统级别的线程基础上进行...
5. **日志与调试**:为了分析线程的行为,开发者通常会记录线程相关的日志信息,包括线程ID、执行时间、状态变化等。这些信息在调试和性能优化时非常有用。 6. **事件驱动**:某些监控任务可能基于事件触发,例如,...