首页 > 其他分享 >day18

day18

时间:2024-10-16 17:12:24浏览次数:1  
标签:Thread void public 线程 new day18 class

Thread类

/*
进程:是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源。
    举例:IDEA, 阿里云盘, wegame, steam
线程:是进程中的单个顺序控制流,是一条执行路径
    一个进程如果只有一条执行路径,则称为单线程程序。
    一个进程如果有多条执行路径,则称为多线程程序。
java提供了一个类用来描述线程:Thread
    线程是程序中执行的线程。
    Java虚拟机允许应用程序同时执行多个执行线程。
    每个线程都有优先权, 具有较高优先级的线程优先于优先级较低的线程执行
    创建线程的方式:实现Runnable接口,借助Thread类创建线程对象和继承Thread类方式
    若将来每一个线程执行的逻辑是一样的话,推荐采用实现Runnable接口方式实现多线程
    若将来每一个线程执行逻辑不一样的话,推荐采用继承Thread类方式实现多线程

 */

代码案例

创建线程的第二种方式:实现Runnable接口,借助Thread类创建线程对象

若将来每一个线程执行的逻辑是一样的话,推荐采用第二种实现Runnable接口方式实现多线程
若将来每一个线程执行逻辑不一样的话,推荐采用第一种继承Thread类方式实现多线程
class MyThread extends Thread{
public MyThread(String name) {
    super(name);
}

@Override
public void run() {
    //run方法是将来线程对象启动时要执行的计算逻辑
    for(int i=1;i<=200;i++){
        System.out.println(getName()+" - "+i);
      }
    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        //创建一个线程对象
//        MyThread t1 = new MyThread();
//        MyThread t2 = new MyThread();
        MyThread t1 = new MyThread("李刚");
        MyThread t2 = new MyThread("钱志强");
        //给线程起名字
        // 方式1:调用setName()方法起名字
//        t1.setName("李刚");
//        t2.setName("钱志强");
        // 方式2:使用构造方法起名字

//        t1.run();
//        t2.run();
        t1.start(); // 系统分配资源给线程t1,启动线程,t1线程具备了执行的资格,具体等到抢到cpu执行权的时候才会执行
        t2.start();
    }
}



/*
    休眠线程
    public static void sleep(long millis)
    加入线程:
    public final void join()
    礼让:
    public static void yield()
    后台线程:
            public final void setDaemon(boolean on)


        用户线程:优先级高于守护线程
        守护线程【后台线程】:当一个程序没有了用户线程,守护线程也就没有了
    中断线程:
            public final void stop() 已弃用
            public void interrupt()
    java所有的线程要想变成运行状态,必须经过抢cpu执行权
 */

线程安全问题

    如何判断一个程序是否存在线程安全的问题呢?
    三要素,缺一不可:
        1、是否存在多线程环境? 是
        2、是否存在共享数据/共享变量?是tickets
        3、是否存在多条语句操作着共享数据/共享变量? 是

    怎么解决?
        方案1:同步代码块
            synchronized(对象){需要同步的代码;}  这里对象要保证多个线程对象唯一的  传入的是对象的类的class对象
            同步方法:锁对象是this
            同步静态方法:锁对象是当前类的class文件对象   类.class
        方案2:lock锁
            // 加锁
              lock.lock();{进程语句}
            //释放锁
              lock.unlock();

synchronized代码案例

lass Window2 implements Runnable{
    int tickets = 200;
    Object obj = new Object();

    @Override
    public void run() {
        while (true){
            synchronized (obj){
                if(tickets>0){ // 1
                    try {
                        // t1
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("当前 " + Thread.currentThread().getName()+" 正在出售第 "+(tickets--)+" 张票");
                }
            }

        }
    }
}


public class SellTicketsDemo2 {
    public static void main(String[] args) {
        Window2 window2 = new Window2();

        Thread t1 = new Thread(window2, "窗口1");
        Thread t2 = new Thread(window2, "窗口2");
        Thread t3 = new Thread(window2, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

lock锁代码案例

package com.shujia.day18;

import java.util.concurrent.locks.ReentrantLock;

/*
    使用lock锁来解决线程安全的问题
 */
class Window4 implements Runnable {
    int tickets = 200;
    Object obj = new Object();
    ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            // 加锁
            lock.lock();
            if (tickets > 0) { // 1
                try {
                    // t1
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("当前 " + Thread.currentThread().getName() + " 正在出售第 " + (tickets--) + " 张票");
            }
            //释放锁
            lock.unlock();
        }
    }
}


public class SellTicketsDemo4 {
    public static void main(String[] args) {
        Window4 window4 = new Window4();

        Thread t1 = new Thread(window4, "窗口1");
        Thread t2 = new Thread(window4, "窗口2");
        Thread t3 = new Thread(window4, "窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

死锁

public class Locks {
    public static final ReentrantLock LOCK1 = new ReentrantLock();
    public static final ReentrantLock LOCK2 = new ReentrantLock();

    private Locks(){}

}
package com.shujia.day18;

/*
    死锁:线程之间存在相互等待的现象

    案例:中国人和外国人
        前提:中国人吃饭必须要两支筷子,外国人吃饭必须一把刀和一把叉
        现在:
            中国人:一支筷子和一把刀
            外国人:一支筷子和一把叉

 */

class Person extends Thread{
    boolean flag;

    public Person(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if(flag){
            synchronized (Locks.LOCK1){
                System.out.println("if lock1");
                // p1
                synchronized (Locks.LOCK2){
                    System.out.println("if lock2");
                }
            }
        }else {
            synchronized (Locks.LOCK2){
                System.out.println("else lock2");
                // p2
                synchronized (Locks.LOCK1){
                    System.out.println("else lock1");
                }
            }
        }
    }
}

public class DieLock {
    public static void main(String[] args) {
        Person p1 = new Person(true);
        Person p2 = new Person(false);

        p1.start();
        p2.start();
    }
}

等待唤醒

/*
    等待唤醒机制:
        生产者
        消费者
        共享数据
        测试类

   等待唤醒机制:前提是要保证程序是线程安全的
 */
public class WaitNotifyDemo1 {
    public static void main(String[] args) {
        Student s = new Student();

        //创建生产者线程对象
        Product product = new Product(s);
        //创建消费者线程对象
        Consumer consumer = new Consumer(s);

        product.start();
        consumer.start();
    }
}
package com.shujia.day18.bao1;

public class Product extends Thread{

    Student s;
    int i =0;

    public Product(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
//        Student s = new Student();
        while (true){
            synchronized (s){
                //作为生产者,在生产数据之前,应该先检查一下数据有没有被消费
                //如果没有被消费,就等待消费者消费
                if(s.flag){
                    //等待 锁对象调用方法等待
                    try {
                        s.wait(); // 程序走到这一步,发生阻塞,直到锁对象再次在程序中被调用了notify()方法
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }


                if(i%2==0){
                    s.setName("李刚");
                    s.setAge(18);
                }else {
                    s.setName("钱志强");
                    s.setAge(10);
                }

                // 生产完数据后,通知消费者来消费数据
                // 由锁对象来通知
                s.notify();
                s.setFlag(true);

                i++;
            }
        }
    }
}
package com.shujia.day18.bao1;

public class Consumer extends Thread{
    Student s;

    public Consumer(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
//        Student s = new Student();
        while (true){
            synchronized (s){
                //消费者在消费数据之前,应该先看一看数据有没有产生【flag是否是true】
                //若没有数据产生,等待生产者生产数据
                if(!s.flag){
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(s.getName()+"-"+s.getAge());

                //消费者消费完数据后,通知生产者生产数据
                s.notify();
                s.setFlag(false);
            }

        }
    }
}

标签:Thread,void,public,线程,new,day18,class
From: https://www.cnblogs.com/flxf/p/18470359

相关文章

  • 初学Java基础Day18---面相对象之抽象类及其抽象方法,接口的使用及其面试题
    一,抽象类及其抽象方法的使用1.抽象方法:没有代码块,使用abstract修饰的方法,交给非抽象子类去实现注意:抽象方法必须在抽象类中。2.抽象类:使用abstract修饰3.代码实现://抽象类publicabstractclassPerson{//抽象方法publicabstractvoideat();}//在......
  • 【21 ZR联赛集训 day18】聚会
    【21ZR联赛集训day18】聚会给出一个由小的编号连向大的编号的DAG,有\(q\)次询问,每次给出\(t\)和若\(s\)个点,表示除这些点之外其他点到\(t\)的最大距离。问距离最远的那个结点编号。\(1\len\le10^5,1\lem\le2\times10^5,\sums\le10^5\)。根号分治。对每个点......
  • 【21 ZR联赛集训 day18】游戏
    【21ZR联赛集训day18】游戏给定长度为\(n\)的序列\(A,B\),每个数形如\(\frac{2^{p_1}3^{p_2}5^{p_3}7^{p_4}11^{p_5}13^{p_6}}{2^{p_7}3^{p_8}5^{p_9}7^{p_{10}}11^{p_{11}}13^{p_{12}}}\)。可以进行若干次操作,每次操作选定\(i(2\lei\len-1),(a_{i-1},a_i,a_{i+1})\gets......
  • 数据结构(Day18)
    一、周学习内容1、9.18数据结构(Day15)-CSDN博客2、9.19数据结构(Day16)-CSDN博客3、9.20 链表目的插入删除不需要移动任何节点(元素)。不需要预估存储空间大小,长度动态增长或减小。概念采用链式存储的线性表。链表的种类单向链表单向链表的概念每个......
  • Day18 二叉树part08| LeetCode 669. 修剪二叉搜索树 , 108.将有序数组转换为二叉搜索树
    669.修剪二叉搜索树669.修剪二叉搜索树classSolution{publicTreeNodetrimBST(TreeNoderoot,intlow,inthigh){if(root==null)returnnull;//处理节点值<low的情况:当前节点及其左子树的所有节点都不在范围内,继续在其右子树上修......
  • 鸿蒙开发入门day18-自定义扩展
    (创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,还请三连支持一波哇ヾ(@^∇^@)ノ)目录自定义扩展能力概述AttributeModifierAttributeUpdaterAttributeModifier概述接口定义行为规格属性设置与修改设置多态样式、事件AttributeUpdater概述接口定......
  • day18打卡
    1.组合classSolution{public:voidbacktracking(intn,intk,intstart){if(path.size()==k){ret.push_back(path);return;}for(inti=start;i<=n-(k-path.size())+1;++i){path.push_back(i);backtracking(n,k,i+1);path.pop_back();}}vector......
  • javase复习day18API
    游戏打包exeMathabs方法的小bug:以int类型为例,取值范围:-2147483648~2147483647如果没有正数与之对应,那么传递负数结果有误-2147483648没有正数对应则结果还是 -2147483648可以使用JDK15后的新方法absExact如果结果有误则会报错packageMathDemo1;publiccla......
  • day18:python 迭代器
    目录一、迭代器1.什么是迭代器2.为何要有迭代器3.如何用迭代器3.1可迭代的对象:但凡内置有__iter__方法的都称之为可迭代的对象3.2调用可迭代对象下的__iter__方法会将其转换成迭代器对象4.可迭代对象与迭代器对象详解5.可迭代对象和迭代器对象有哪些?6.for循环的......
  • 代码随想录Day18
    530.二叉搜索树的最小绝对差给你一个二叉搜索树的根节点root,返回树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。示例1:输入:root=[4,2,6,1,3]输出:1示例2:输入:root=[1,0,48,null,null,12,49]输出:1提示:树中节点的数目范围是......