Java多线程入门2

线程死锁简单示例

package second.study;

public class Test {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new DeadLock(true));
        Thread thread2 = new Thread(new DeadLock(false));
        thread1.start();
        thread2.start();
    }
}

class DeadLock implements Runnable {

    private boolean flag;

    DeadLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            while (true) {
                synchronized (Lock.obj1) {
                    System.out.println("if Lock1");
                    synchronized (Lock.obj2) {
                        System.out.println("if Lock2");
                    }
                }
            }
        } else {
            while (true) {
                synchronized (Lock.obj2) {
                    System.out.println("else Lock2");
                    synchronized (Lock.obj1) {
                        System.out.println("else Lock1");
                    }
                }
            }
        }

    }
}

class Lock {
    static Object obj1 = new Object();
    static Object obj2 = new Object();
}

多线程间通信

  解决线程间通信的安全问题的关键是,在操作共享数据时使用同一把锁将共享数据进行锁定!这样,别的线程就算获得了cpu的执行权,没有锁也无法运行共享数据。

  wait(); notify(); notifyAll();都使用在同步中,因为要对持有监视器(锁)的线程进行操作。只有锁对象内才具有wait()等方法。

//单生产者单消费者多线程代码package second.study;

public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        new Thread(new Input(p)).start();
        new Thread(new Output(p)).start();
    }
}

class Person {
    private String name;
    private String sex;
    private boolean flag = false;

    public synchronized void set(String name, String sex) {//在锁对象内使用wait()和notify()方法
        if (flag) {//if语句只适用于单生产者单消费者问题
            try {
                this.wait();
            } catch (Exception ex) {
            }
        }
        this.name = name;
        this.sex = sex;
        flag = true;
        this.notify();//notify()语句也只适用于单生产者单消费者问题
    }

    public synchronized void get() {
        if (!flag) {
            try {
                this.wait();
            } catch (Exception ex) {
            }
        }
        System.out.println(name + "...." + sex);
        flag = false;
        this.notify();
    }
}

class Input implements Runnable {
    private Person p;

    public Input(Person p) {
        this.p = p;
    }

    @Override
    public void run() {
        int x = 0;
        while (true) {
            if (x == 0) {
                p.set("John", "man");
            } else {
                p.set("丽丽", "女女女女");
            }
            x = (x + 1) % 2;
        }
    }

}

class Output implements Runnable {
    Person p;

    public Output(Person p) {
        this.p = p;
    }

    @Override
    public void run() {
        while (true) {
            p.get();
        }
    }
}

多生产者多消费者问题

package second.study;

public class Test {
    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(new Producer(resource)).start();
        new Thread(new Producer(resource)).start();
        new Thread(new Consumer(resource)).start();
        new Thread(new Consumer(resource)).start();
    }
}

class Resource{
    private int count;
    private String name;
    private boolean flag = false;
    public synchronized void set(String name) {
        while(flag) {
            try {
                wait();
            }catch(InterruptedException ex) {

            }
        }
        this.name = name +  "--" + count++;
        System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
        flag = true;
        this.notifyAll();
    }
    public synchronized void out() {
        while(!flag) {
            try {
                wait();
            }catch(InterruptedException ex) {

            }
        }
        System.out.println(Thread.currentThread().getName()+"......消费者......"+this.name);
        flag = false;
        this.notifyAll();
    }
}

class Producer implements Runnable{
    private Resource res;
    public Producer(Resource res) {
        this.res = res;
    }
    @Override
    public void run() {
        while(true) {
            res.set("商品");
        }
    }
}

class Consumer implements Runnable{
    private Resource res;
    public Consumer(Resource res) {
        this.res = res;
    }
    @Override
    public void run() {
        while(true) {
            res.out();
        }
    }

}

在JDK1.5以后,将监视器对象(锁)和监视器方法(wait();等)替换成了Lock接口对象和Condition接口对象。并且该监视器方法依然可以通过锁对象获取,并且可以创建多个锁的监视器方法对象,可以理解为可以创建多个线程池(自己的理解),用于唤醒相应线程池中的一个线程,提高速度。

package second.study;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    public static void main(String[] args) {
        Resource resource = new Resource();
        new Thread(new Producer(resource)).start();
        new Thread(new Producer(resource)).start();
        new Thread(new Consumer(resource)).start();
        new Thread(new Consumer(resource)).start();
    }
}

class Resource {
    private int count;
    private String name;
    private boolean flag = false;
    Lock lock = new ReentrantLock();//Lock是一个接口,需要使用其可创建对象的子类;
    Condition condition_pro = lock.newCondition();//使用Lock对象中的方法获取监视器方法对象
    Condition condition_con = lock.newCondition();

    public void set(String name) {
        lock.lock();
        try {
            while (flag) {
                condition_pro.await();//线程0线程1进入一个线程池
            }
            this.name = name + "--" + count++;
            System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
            flag = true;
            condition_con.signal();
        } catch (InterruptedException ex) {

        } finally {
            lock.unlock();// 资源一定要释放
        }

    }

    public void out() {
        lock.lock();
        try {
            while (!flag) {
                condition_con.await();//线程2和线程2进去一个线程池
            }
            System.out.println(Thread.currentThread().getName() + "......消费者......" + this.name);
            flag = false;
            condition_pro.signal();

        }catch(InterruptedException ex) {

        }finally {
            lock.unlock();
        }

    }
}

class Producer implements Runnable {
    private Resource res;

    public Producer(Resource res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            res.set("商品");
        }
    }
}

class Consumer implements Runnable {
    private Resource res;

    public Consumer(Resource res) {
        this.res = res;
    }

    @Override
    public void run() {
        while (true) {
            res.out();
        }
    }

}

如何停止线程?

  stop方法已经过时,那么停止线程只有一种,run方法结束。可以通过在主线程来控制run()方法中的标记来控制其他线程的结束。当其他线程中有wait();sleep();方法时,可能其他线程无法判断标记而使线程处于冻结状态,这时,可以使用Thread类中的interrupt()方法。当主线程执行到interrupt方法来中断线程,但是其他同步线程没有使用wait方法,这时interrupt方法对该线程不起作用,但是主线程会一直监视该线程的状态,当该线程执行到了wait方法,会立即响应中断,引发interruptException异常。然后会以下是测试代码:

package second.study;

public class Test {
    public static void main(String[] args) {
        StopThread stopThread = new StopThread();
        Thread t1 = new Thread(stopThread);
        Thread t2 = new Thread(stopThread);
        t1.start();
        t2.start();
        int num = 0;
        while(true) {
            if(num == 60) {
                t1.interrupt();
                t2.interrupt();
                System.out.println("main interrupt");//判定主线程在t1和t2线程执行wait方法之前先执行了interrupt方法。
                break;
            }
            num++;
            System.out.println(Thread.currentThread().getName() + "......" + num);
        }
    }
}

class StopThread implements Runnable{
    private boolean flag = true;
    @Override
    public synchronized void run() {
        while(flag) {
            try {
                int num = 0;
                while(true) {
                    System.out.println(Thread.currentThread().getName() + "..." + num);
                    if(num == 100) {
                        System.out.println(Thread.currentThread().getName() + "..." + "run");
                        wait();
                    }
                    num++;
                }
            }catch(InterruptedException ex) {
                System.out.println(Thread.currentThread().getName() + "..." + "Exception");
                  flag = false;//结束当前线程

            }
        }
    }

    public void changeFlag() {
        flag = false;
    }
}

守护线程

  也称为后台线程,当前程线程执行完毕后,后台线程会自动结束。当正在运行的线程全部为首部线程时,JVM退出。

  Thread类中的setDaemon方法。在开启线程(使用start()方法)前使用。

多线程的Join方法

  当A线程执行到了B线程的.join方法时,A就会等待,当B线程运行结束后,A线程才会执行。

  join可以用来临时加入线程。

线程优先级

  线程的优先级分为10级,可以使用setPriority(Thread.MAX_PRIORITY or Thread.MIN_PRIORITY or Thread.NORM_PRIORITY),来设置线程的优先级。

原文地址:https://www.cnblogs.com/star-491849224/p/12489248.html

时间: 2024-11-29 12:07:28

Java多线程入门2的相关文章

java多线程入门学习(一)

java多线程入门学习(一) 一.java多线程之前 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.     线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.     线程和进程一样分为五个阶段:创建.就绪.运行.阻塞.终止.     多进程是指操作系统能同时运行多个任务(程序).     多线程是指在同一程序中有多个顺序流在执行. 在java中要想实现多线程,有两种手段,一种是继承T

(转载)Java多线程入门理解

转载出处http://blog.csdn.net/evankaka 写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalan

JAVA多线程入门

为什么使用多线程 进程之间不能共享内存,但线程之间共享内存很容易 系统创建进程需要为该进程重新分配系统资源,但创建线程代价小得多,因此使用多线程来实现多任务并发比多进程的效率高 JAVA内置了多线程功能支持,而不是单纯的作为底层操作系统的调度方式,从而简化了JAVA的多线程编程 线程的创建 继承Thread类(可直接使用this关键字获得当前对象,多个线程无法共享线程类的实例变量) 实现Runnable接口(必须使用Thread.currentThread()方法,多个线程可以共享线程类的实例变

Java多线程入门知识点梳理

前言 在多核时代,高并发时代,对系统并行处理能力有很高要求.多线程就是这个时代最好的产物.通过使用多线程可以增强系统并行处理能力,提高CPU资源的有效利用:从而提高系统的处理能力.常见应用场景如:多窗口售票.生产消费模式.异步提交信息(如日志.发送消息),只要系统需要并行任务处理的场景都可以考虑使用多线程.当然它也有缺点,线程由CPU调度.程序员无法干涉.多线程的随机性,这就会增加不可控性,得出的数据重复.错乱等现象...这篇文章是从关键点上进行整理...后续会针对相关关键点制作相关系列文章..

Java多线程入门中几个常用的方法

一.currentThread()方法 currentThread方法就是返回当前被调用的线程. 该方法为一个本地方法,原码如下: /** * Returns a reference to the currently executing thread object. * * @return the currently executing thread. */ public static native Thread currentThread(); 可以看出他返回的是一个线程对象. 下面来看一个列

(Java多线程系列一)快速入门

Java多线程快速入门 1.线程和进程的区别 进程是所有线程的集合,每一个线程是进程的一条执行路径. 2.多线程的应用场景 多线程主要体现在提高程序的效率,比如迅雷多线程下载,多线程分批发送短信等. 3.多线程的创建方式 (1)继承Thread类,重写run()方法 class ThreadDemo extends Thread { @Override public void run() { System.out.println("这里是子线程"); System.out.printl

java 多线程 快速入门

------------恢复内容开始------------ java 多线程 快速入门 1. 进程和线程 什么是进程? 进程是正在运行的程序它是线程的集合 进程中一定有一个主线程 一个操作系统可以有多个线程  什么是线程? 线程就是独立的运行一条执行路径 一个独立的执行单元 , 一个执行流程 为什么要使用多线程? 多线程提高程序效率 , 使用多线程 , 每个线程互补影响 2.创建线程的方式有哪些 1.使用继承 Thread类方式 如下示例 结果 1.继承 Thread 类 class Crea

java多线程编程从入门到卓越(超详细总结)

导读:java多线程编程不太熟?或是听说过?或是想复习一下?找不到好的文章?别担心我给你们又安利一波,文章内容很全,并且考虑到很多开发中遇到的问题和解决方案.循环渐进,通俗易懂,文章较长,建议收藏再看! 往期精彩放送:一文搞定Java的输入输出流等常见流 一文搞定Java集合类,你还在为Java集合类而烦恼吗? 文章目录 1.多线程的概念 2.多线程并发 3.多线程程序设计 继承Thread类创建线程 新建类实现Runnable接口创建线程 改进(匿名内部类方式) 获取线程的名字和当前线程对象

Java多线程学习

写在前面的话:此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢?如果你觉得此文很简单,那推荐你看看Java并发包的的线程池(Java并发编程与技术内幕:线程池深入理解),或者看这个专栏:Java并发编程与技术内幕.你将会对Java里头的高并发场景下的线程有更加深刻的理解. 目录(?)[-] 一扩展javalangThread类 二实现javalangRunnable接口 三Thread和Runnable的区别 四线