`
bit1129
  • 浏览: 1051435 次
  • 性别: 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线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解Java线程讲解

    线程 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线程

    java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-优先级 ...

    Java线程Java线程Java线程Java线程

    Java线程Java线程Java线程Java线程Java线程Java线程

    java线程 线程学习资料 java线程教程

    java线程 线程 教程 java线程教程 java线程学习资料 本教程有什么内容? 本教程研究了线程的基础知识— 线程是什么、线程为什么有用以及怎么开始编写使用线程的简单 程序。 我们还将研究更复杂的、使用线程的应用...

    java 线程java 线程

    java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程java 线程

    Java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调度-休眠 Java线程:线程的调度-...

    Java线程基础教程完整版

    Java线程基础教程完整版

    Java线程模块Java线程之秒表

    Java线程模块Java线程之秒表新手学习Java线程模块时,利用Java中设置线程的暂停间隔,做的简易秒表

    java多线程笔记

    Java线程:概念与原理 2 一、操作系统中线程和进程的概念 2 二、Java中的线程 3 三、Java中关于线程的名词解释 3 四、线程的状态转换和生命周期 4 Java线程:创建与启动 7 Java线程:线程名称的设定及获取 10 Java...

    java 线程 dump 分析工具 2.3.3

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

    java线程同步java线程同步

    java线程同步java线程同步java线程同步

    Java的线程和Java AppletJava的线程和Java AppletJava的线程和Java Applet

    Java的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java AppletJava的线程和Java Applet

    java线程.pdf

    java线程.pdf java 学习java

    Java线程Java线程

    java 线程 新手java 线程 新手java 线程 新手java 线程 新手

    java线程分析工具TDA

    分析java线程日志的工具,使用jstack把java线程日志dump下来,然后上传到该工具,就可以查看线程阻塞情况等信息。

    Java 模拟线程并发

    Java 模拟线程并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发 Java, 模拟线程并发,线程,并发

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程读取文件

    Java多线程读大文件 java多线程写文件:多线程往队列中写入数据

Global site tag (gtag.js) - Google Analytics