`
bit1129
  • 浏览: 1069765 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【Java线程一】线程基础

 
阅读更多

Java多线程状态图

 

Java多线程状态图一:

 

 

 

 

Java多线程状态图二:

 

 

 

 

Java线程状态3

 



 

 线程阻塞的原因:

 

1.IO阻塞,比如线程状态一种的Blocked

2.线程互斥导致的阻塞,比如尝试获得一个对象锁,而这个锁被其它对象持有,那么这个线程只能等待。 一个对象可以有多个线程等待获得它的锁,因此,这里有一个对象锁池的概念(Lock Pool)。当持有锁的线程释放锁后,默认情况下,其它线程竞争这个把锁,究竟哪个线程获得这个锁,是与CPU调度有关的。如果要获得先等待先获得的这种公平锁,需要使用JUC提供的锁,比如ReentrantLock

3.线程同步导致的阻塞,比如一个线程只能等到它等待的事件发生了(wait/notify/notifyAll),这个线程才能恢复到可运行态。

 

 

wait/notify示例---生产者消费者问题

 

 不优雅的做法:

当plates对象执行notifyAll动作时,不管是消费线程和生产线程都被唤醒了。事实上,在调用notifyAll时,上下文能够确定是消费者消费了之后唤醒生产者线程可以继续生产了,还是生产者生产了之后唤醒消费者线程继续消费。

 

 

import java.util.*;

public class WaitAndNotifyTest {

    private static volatile boolean shutdown = false;

    public static void main(String[] args) {

        final Queue<Integer> plates = new LinkedList<Integer>();

        Thread[] consumers = new Thread[3];

        for (int i = 0; i < consumers.length; i++) {

            consumers[i] = new Thread() {
                @Override
                public void run() {

                    while (!shutdown) {

                        synchronized (plates) {
                            while (plates.size() <= 0) {
                                try {
                                    plates.wait();
                                } catch (InterruptedException e) {
                                }
                            }
                            if (plates.size() > 0) {
                                System.out.println(plates.poll() + " is consumed");
                                plates.notifyAll(); //唤醒所有的线程,不管是生产者还是消费者,因为它们都同步于plates对象锁
                                try {
                                    Thread.sleep(100);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }

                        }

                    }

                }
            };
            consumers[i].start();
        }


        Thread[] producers = new Thread[5];

        for (int i = 0; i < producers.length; i++) {
            producers[i] = new Thread() {
                @Override
                public void run() {
                    while (!shutdown) {

                        synchronized (plates) {
                            while (plates.size() == 10) {
                                try {
                                    plates.wait();
                                } catch (InterruptedException e) {
                                }
                            }
                            if (plates.size() < 10) {
                                int i = new Random().nextInt();
                                plates.offer(i);
                                plates.notifyAll(); //唤醒所有的线程,不管是生产者还是消费者,因为它们都同步于plates对象锁
                                System.out.println(i + " is put into the plate");
                                try {
                                    Thread.sleep(100);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }

                }
            };
            producers[i].start();
        }

        try {
            Thread.sleep(6000);
            shutdown = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

 

 

错误的做法一:

下面的代码生产和消费使用了两把锁,但是应该是有问题的。这应该是JUC的多路条件等待要解决的事情!!

 

 

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ThreadLocalRandom;

class Plate<T> {
    private final Object PLATE_NOT_FULL = new Object();
    private final Object PLATE_NOT_EMPTY = new Object();

    private final Queue<T> plates = new LinkedList<T>();
    private int size;

    public Plate(int size) {
        this.size = size;
    }

    public void produce(T fruit) {
        synchronized (PLATE_NOT_FULL) {
            if (plates.size() >= size) {
                try {
                    System.out.println(Thread.currentThread().getName() + ", The plate is full..waiting to put into the plate");
                    PLATE_NOT_FULL.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (PLATE_NOT_EMPTY) {
            if (plates.size() < size) { //程序运行到这里,有可能plates已经满了,因此,这个操作不会将fruit加入到盘子中,也就是说,调用produce方法的线程丢失了本次生产的fruit
                plates.offer(fruit);
                System.out.println(Thread.currentThread().getName() + ", The plate is not full..put the fruit into the plate," + fruit);
                PLATE_NOT_EMPTY.notifyAll();
            }
        }

    }

    public T consume() {
        T fruit = null;
        synchronized (PLATE_NOT_EMPTY) {
            if (plates.size() <= 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + ", The plate is empty..waiting to consume");
                    PLATE_NOT_EMPTY.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (PLATE_NOT_FULL) {
            if (plates.size() > 0) { //Safe guard
                fruit = plates.poll();
                System.out.println(Thread.currentThread().getName() + ", The plate is not empty..consume" + fruit);
                PLATE_NOT_FULL.notifyAll();
                return fruit;
            }
        }

        return fruit;
    }

}

public class ThreadCommunication {

    private static volatile boolean shutdown = false;

    public static void main(String[] args) {

        final Plate<Integer> plate = new Plate<Integer>(8);

        Thread[] consumers = new Thread[5];

        for (int i = 0; i < consumers.length; i++) {

            consumers[i] = new Thread() {
                @Override
                public void run() {

                    while (!shutdown) {
                        plate.consume();
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            };
            consumers[i].start();
        }


        Thread[] producers = new Thread[5];

        for (int i = 0; i < producers.length; i++) {
            producers[i] = new Thread() {
                @Override
                public void run() {
                    while (!shutdown) {
                        plate.produce(ThreadLocalRandom.current().nextInt(100, 1000));
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            producers[i].start();
        }

        try {
            Thread.sleep(6000);
            shutdown = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

 

 错误做法二:线程死锁

 

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ThreadLocalRandom;

class Plate<T> {
    private final Object PLATE_NOT_FULL = new Object();
    private final Object PLATE_NOT_EMPTY = new Object();

    private final Queue<T> plates = new LinkedList<T>();
    private int size;

    public Plate(int size) {
        this.size = size;
    }

    public void produce(T fruit) {
        synchronized (PLATE_NOT_FULL) {
            if (plates.size() >= size) {
                try {
                    System.out.println(Thread.currentThread().getName() + ", The plate is full..waiting to put into the plate");
                    PLATE_NOT_FULL.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (PLATE_NOT_EMPTY) {
                if (plates.size() < size) { //Safe guard
                    plates.offer(fruit);
                    System.out.println(Thread.currentThread().getName() + ", The plate is not full..put the fruit into the plate," + fruit);
                    PLATE_NOT_EMPTY.notifyAll();
                }
            }
        }

    }

    public T consume() {
        T fruit = null;
        synchronized (PLATE_NOT_EMPTY) {
            if (plates.size() <= 0) {
                try {
                    System.out.println(Thread.currentThread().getName() + ", The plate is empty..waiting to consume");
                    PLATE_NOT_EMPTY.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            synchronized (PLATE_NOT_FULL) {
                if (plates.size() > 0) { //Safe guard
                    fruit = plates.poll();
                    System.out.println(Thread.currentThread().getName() + ", The plate is not empty..consume" + fruit);
                    PLATE_NOT_FULL.notifyAll();
                    return fruit;
                }
            }
        }

        return fruit;
    }

}

public class ThreadCommunication {

    private static volatile boolean shutdown = false;

    public static void main(String[] args) {

        final Plate<Integer> plate = new Plate<Integer>(8);

        Thread[] consumers = new Thread[5];

        for (int i = 0; i < consumers.length; i++) {

            consumers[i] = new Thread() {
                @Override
                public void run() {

                    while (!shutdown) {
                        plate.consume();
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            };
            consumers[i].start();
        }


        Thread[] producers = new Thread[5];

        for (int i = 0; i < producers.length; i++) {
            producers[i] = new Thread() {
                @Override
                public void run() {
                    while (!shutdown) {
                        plate.produce(ThreadLocalRandom.current().nextInt(100, 1000));
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            producers[i].start();
        }

        try {
            Thread.sleep(6000);
            shutdown = true;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

 

 典型的:

 

synchronized(A) {
  synchronized(B)
}
和
synchronized(B) {
  synchronized(A)
}

产生死锁问题

 

 

 

 

  • 大小: 15.2 KB
  • 大小: 19.1 KB
  • 大小: 25.3 KB
分享到:
评论

相关推荐

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...

    java 线程工具类 java 线程工具类

    java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具...

    java线程.pdf

    ### Java线程基础 在Java语言中,线程是程序执行流的基本单元。一个标准的Java应用程序至少会有一个线程,即主线程,用于执行程序的主要逻辑。通过创建多个线程,可以实现并发执行任务,提高程序的运行效率和响应...

    Java线程基础教程完整版

    本教程将深入讲解Java线程的基础知识,帮助你掌握多线程编程的核心技能。 1. **线程的创建** - **继承Thread类**:创建一个新的类,该类继承自Thread类,然后重写它的`run()`方法。通过创建此类的实例并调用其`...

    Java线程详解大全

    总之,Java线程是并发编程的基础,理解和掌握线程的生命周期、实现方式和同步机制对于编写高效、安全的多线程程序至关重要。在实际应用中,根据需求选择合适的线程实现策略,并结合同步机制,可以有效地利用系统资源...

    Java线程状态流转图

    Java线程状态流转图是一种用于描述Java线程生命周期中不同的状态和状态转换的图形表示方式。该图形展示了Java线程从创建到终止的整个生命周期,并详细介绍了每种状态的特点和转换规则。 NEW(初始化状态) 在Java...

    java多线程Demo

    Java线程有10个优先级(MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY),默认优先级是NORM_PRIORITY。但是,线程优先级并不保证绝对的执行顺序,操作系统调度策略可能影响实际执行顺序。 7. join()方法: 一个线程...

    Java线程(第三版)

    《Java线程(第三版)》是一本深入探讨Java线程技术的专业书籍,旨在帮助开发者理解和掌握Java平台上的多线程编程。Java线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而充分利用系统资源,提高程序的...

    Java线程.ppt

    Java线程是Java编程中的重要概念,特别是在多核处理器和并发处理中不可或缺。Java线程允许程序在同一时间执行多个不同的任务,从而提高了程序的效率和响应性。在燕山大学信息学院计算机系的课程中,李峰教授讲解了...

    JAVA单线程多线程

    在Java编程环境中,单线程指的是程序执行过程中只有一个线程在运行。这意味着任何时刻只能执行一个任务,上一个任务完成后才会进行下一个任务。单线程模型简化了程序设计,降低了程序复杂度,使得开发者可以更专注于...

    Java线程使用教程

    Java线程是Java编程语言中的一个核心概念,它允许程序同时执行多个任务,极大地提高了程序的并发性和效率。本教程将深入探讨Java线程的使用,帮助开发者掌握这一关键技术。 一、线程基础 1. **线程的概念**:线程...

    java线程实例 各种小Demo

    Java线程是多任务编程的重要概念,它允许程序同时执行多个独立的任务,从而提高系统效率和响应速度。在Java中,线程可以分为用户线程和守护线程,前者是程序运行的基础,而后者是在所有用户线程结束时才终止的后台...

    java线程深入解析

    Java线程的深入理解和熟练掌握是Java程序员必备的技能,它涉及到程序的性能优化、并发控制和安全性,是开发复杂多线程应用的基础。在实际开发中,合理使用线程同步机制和理解线程调度原理,可以有效避免死锁、活锁等...

    java 线程 dump 分析工具 2.3.3

    Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的统计信息,提供关于锁定监视器...

    java线程分析工具TDA

    TDA(Thread Dump Analyzer)是一款强大的Java线程分析工具,它能够帮助开发者深入理解应用在运行时的线程状态,包括线程的阻塞情况、等待资源、死锁等问题。下面将详细介绍TDA的使用方法、功能以及它如何帮助我们...

    java线程入门级书籍

    #### 一、Java线程基础知识概述 **1.1 什么是线程?** 线程是程序执行流的最小单元,是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。在Java中,线程是一种轻量级的进程,...

    JAVA线程dump的分析

    JAVA线程dump的分析 JAVA线程dump是指在JAVA程序中,当前线程的状态和调用堆栈的快照,能够帮助开发者了解当前程序的执行情况,诊断问题和性能瓶颈。生成JAVA线程dump的方法在不同的操作系统下是不同的,在Windows...

    JAVA线程学习(源代码)

    总的来说,"JAVA线程学习(源代码)"涵盖了Java线程的基础知识和高级特性,包括线程的创建、管理、同步和通信。通过分析和实践这些源代码,你可以深入了解Java并发编程的精髓,提高你的多线程编程能力。

    java线程文档大全

    这些知识点覆盖了Java线程编程的基础到高级应用,对于Java开发者来说,理解和掌握这些内容对于编写高效、安全的并发程序至关重要。通过深入学习和实践,开发者能够更好地应对多线程环境下的挑战。

Global site tag (gtag.js) - Google Analytics