首页 > 其他分享 >多线程

多线程

时间:2022-11-09 20:56:49浏览次数:39  
标签:account Thread 线程 new 多线程 public

多线程

image-20220721161145845

使用继承Thread类开启多线程

例:

package thread;

//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
public class TestThread01 extends Thread{
    @Override
    public void run() {
        //run()方法线程体
        for (int i = 0; i < 20; i++) {
            System.out.println("我再看代码-------"+i);
        }
    }
    public static void main(String[] args) {
        //main线程,主线程

        //创建一个线程对象
        TestThread01 testThread01 = new TestThread01();
        //调用start()方法开启线程
        testThread01.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("我在学习多线程----"+i);
        }
        //输出结果交替
    }
}

输出结果:

我在学习多线程----0
我再看代码-------0
我在学习多线程----1
我再看代码-------1
我再看代码-------2
我再看代码-------3
我再看代码-------4
我再看代码-------5
我再看代码-------6
我再看代码-------7
我再看代码-------8
我再看代码-------9
我再看代码-------10
我再看代码-------11
我再看代码-------12
我再看代码-------13
我在学习多线程----2
我在学习多线程----3
我在学习多线程----4
我在学习多线程----5
我在学习多线程----6
我在学习多线程----7
我在学习多线程----8
我在学习多线程----9
我在学习多线程----10
我在学习多线程----11
我在学习多线程----12
我在学习多线程----13
我再看代码-------14
我在学习多线程----14
我再看代码-------15
我在学习多线程----15
我再看代码-------16
我在学习多线程----16
我在学习多线程----17
我在学习多线程----18
我在学习多线程----19
我再看代码-------17
我再看代码-------18
我再看代码-------19

进程已结束,退出代码0
  • 总结:注意,线程开启不一定立刻执行,由cpu调度执行
  • 步骤:
    • 自定义线程类继承Thread类
    • 重写run()方法,编写线程执行体
    • 创建线程对象,调用start()方法启动线程

使用Runnable实现接口

  • 例:

    package thread;
    
    public class TestThread03 implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                System.out.println("我在看代码!====="+i);
            }
        }
    
    
        public static void main(String[] args) {
            TestThread03 testThread03 = new TestThread03();
    
    //        Thread thread = new Thread(testThread03);
    //        thread.start();
            new Thread(testThread03).start();
    
            for (int i = 0; i < 20; i++) {
                System.out.println("我在学习双线程====="+i);
            }
        }
    }
    

小结

  • 继承Thread类

    • 子类继承Thread类具有多线程能力
    • 启动线程:子类对象.start()
    • 不建议使用:避免OOP单继承局限性
  • 实现Runnable接口

    • 实现接口Runnable具有多线程能力
    • 启动进程:传入对象+Thread对象.start()
    • 推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

龟兔赛跑例子

package thread;

public class TestThread04 implements Runnable{
    private static String winner;

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {

            if (Thread.currentThread().getName().equals("兔子")){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步");
            boolean flag = gameOver(i);
            if (flag==true){
                break;
            }
        }
    }

    private boolean gameOver(int step){
        if (step==100){
            this.winner = Thread.currentThread().getName();
            System.out.println("Winner is "+winner);
            return true;
        }
        if (winner !=null){
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        TestThread04 testThread04 = new TestThread04();

        new Thread(testThread04,"兔子").start();
        new Thread(testThread04,"乌龟").start();

    }


}

线程休眠sleep

  • sleep(时间)指定当前线程阻塞的毫秒数

  • sleep存在异常InterruptedException;

  • sleep事件达到后线程进入就绪状态

  • sleep可以模拟网络延时,倒计时等

  • 例子:抢火车票

    public class TestSleep implements Runnable{
    
        private int ticketNum = 10;
        @Override
        public void run() {
            while(true){
                if (ticketNum <= 0){
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName()+"抢到了第"+ticketNum--+"张票!");
            }
        }
    
    
        public static void main(String[] args) {
            TestSleep ticket = new TestSleep();
            new Thread(ticket,"小明").start();
            new Thread(ticket,"黄牛").start();
            new Thread(ticket,"旅游公司").start();
        }
    }
    

线程礼让yield

  • 礼让线程,让当前正在执行的线程暂停,但不堵塞

  • 将线程从运行状态转为就绪状态

  • 让CPU重新调度,礼让不一定成功

  • 例子:

    public class TestYield implements Runnable{
        @Override
        public void run() {
            System.out.println("线程开始执行"+Thread.currentThread().getName());
            Thread.yield();
            System.out.println("线程停止执行"+Thread.currentThread().getName());
        }
    
    
        public static void main(String[] args) {
            TestYield testyield = new TestYield();
            new Thread(testyield,"a").start();
            new Thread(testyield,"b").start();
    
        }
    }
    

    线程强制执行join

public class TestJoin implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("vip线程执行第"+i+"次");
        }
    }


    public static void main(String[] args) throws InterruptedException {
        TestJoin testJoin = new TestJoin();
        Thread thread = new Thread(testJoin);
        thread.start();
        for (int i = 0; i < 100; i++) {
            if (i==30){
                thread.join();
            }
            System.out.println("主线程"+i);
        }
    }
}

线程优先级

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行

  • 线程的优先级用数字表示,范围1~10

    • Thread.MIN_PRIORITY = 1
    • Thread.MAX_PRIORITY = 10
    • Thread.NORM_PRIORITY = 5
  • 使用一下方式改变或获取优先级

    • getPriority
    • .setPriprity(int xxx)
  • 优先级低只是意味着获得调度的概率低,并不是优先级第就不会被调用了。

  • 优先级的设定建议在start()调度前

守护线程daemon

  • 线程分为用户线程和守护线程

  • 虚拟机必须确保用户线程执行完毕

  • 虚拟机不用等待守护线程执行完毕

  • 例子:上帝守护我们

    public class TestDaemon {
    
        public static void main(String[] args) {
            You you = new You();
            God god = new God();
            Thread thread = new Thread(god);
            thread.setDaemon(true);
    
            thread.start();
            new Thread(you).start();
        }
    }
    
    class You implements Runnable{
    
        @Override
        public void run() {
            for (int i = 0; i < 36500; i++) {
                System.out.println("开心的活着!");
            }
            System.out.println("拜拜了这个美丽的世界!!!!");
            System.out.println("=================================");
        }
    }
    
    class God implements Runnable{
    
        @Override
        public void run() {
            while(true){
                System.out.println("上帝守护者你!");
            }
        }
    }
    
    

同步方法synchronized

  • synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得该方法的对象的锁才能执行,否则相乘会堵塞,方法一旦执行,就独占该锁,值到该方法返回才释放锁,后面被堵塞的线程才能获得这个锁,继续执行

    public synchronized void method(int args){}
    

    或者使用synchronized块

    synchronized(Obj){}
    
  • 例:(银行取钱)改前

    public class UnsafeBank {
    
        public static void main(String[] args) {
            Account account = new Account(100,"张三");
            Drawing you =new Drawing(account,50,"boyfriend");
            Drawing girlfriend =new Drawing(account,100,"girlfriend");
            you.start();
            girlfriend.start();
        }
    }
    
    
    
    
    //账户
    class Account{
        int money;//余额
        String idname;//卡名
    
        public Account(int money, String idname) {
            this.money = money;
            this.idname = idname;
        }
    }
    
    
    //银行
    class Drawing extends Thread{
        Account account;
        int drawingMoney;
        int nowMoney;
        public Drawing(Account account,int drawingMoney,String idname){
            super(idname);
            this.account =account;
            this.drawingMoney = drawingMoney;
        }
    
        @Override
        public void run() {
            if(account.money - drawingMoney < 0){
                System.out.println(Thread.currentThread().getName()+"钱不够,不能取!");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            account.money = account.money - drawingMoney;
            nowMoney = nowMoney + drawingMoney;
            System.out.println(account.idname+"账户余额为"+account.money);
            System.out.println(Thread.currentThread().getName()+"手里的钱为"+nowMoney);
        }
    }
    

    改后:

    public class UnsafeBank {
    
        public static void main(String[] args) {
            Account account = new Account(100,"张三");
            Drawing you =new Drawing(account,50,"boyfriend");
            Drawing girlfriend =new Drawing(account,100,"girlfriend");
            you.start();
            girlfriend.start();
        }
    }
    
    
    
    
    //账户
    class Account{
        int money;//余额
        String idname;//卡名
    
        public Account(int money, String idname) {
            this.money = money;
            this.idname = idname;
        }
    }
    
    
    //银行
    class Drawing extends Thread{
        Account account;
        int drawingMoney;
        int nowMoney;
        public Drawing(Account account,int drawingMoney,String idname){
            super(idname);
            this.account =account;
            this.drawingMoney = drawingMoney;
        }
    
        @Override
        public void run() {
            synchronized (account){
                if(account.money - drawingMoney < 0){
                    System.out.println(Thread.currentThread().getName()+"钱不够,不能取!");
                    return;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                account.money = account.money - drawingMoney;
                nowMoney = nowMoney + drawingMoney;
                System.out.println(account.idname+"账户余额为"+account.money);
                System.out.println(Thread.currentThread().getName()+"手里的钱为"+nowMoney);
    
            }
        }
    }
    

死锁

  • 产生死锁的四个必要条件:

    1. 互斥条件:一个资源每次只能被一个进程使用
    2. 请求与保持条件:一个进程因请求资源而堵塞时,对以获得的资源保持不放。
    3. 不剥夺条件:进程已获得的资源,在未使用之前,不能强行剥夺
    4. 循环等待条件:若干进程意见形成一种头尾相接的循环等待资源关系
  • 避免死锁条件:只要想办法破其中任意一个或者多个条件就可以避免死锁发生

标签:account,Thread,线程,new,多线程,public
From: https://www.cnblogs.com/jiangwang-jzh/p/16875137.html

相关文章

  • 线程同步-读者写者问题(多线程)
    问题描述有读者和写者两个并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可......
  • 读者-写者(多线程)
    同步互斥问题-读者写者问题之写者优先(一)问题要求1.读者-写者问题的读写操作限制(仅读者优先或写者优先)写-写互斥,即不能有两个写者同时进行写操作。读-写互斥,即不能......
  • 读者-写者(多线程)
    读者-写者(多线程)读者写者问题抽象解释多个进程访问一个共享的数据区读者(读进程)只能读数据,写者(写进程)只能写数据适用于数据库、文件、内存、寄存器等数据区的访问模型......
  • 读者-写者(多线程)
    写者优先截图代码#include<stdio.h>#include<stdlib.h>#include<time.h>#include<sys/types.h>#include<pthread.h>#include<semaphore.h>#include......
  • 多进程多线程记录第一篇
    多线程与多进程一,什么是进程,什么是线程?​ 进程:运行中的程序.每次我们执行一个程序,咱们的操作系统对自动的为这个程序准备一些必要的资源(例如,分配内存,创......
  • 读者-写者(多线程)
    0推荐在openEuer上实现1描述操作系统中“读者-写者”问题,理解问题的本质,提交你理解或查找到的文本资料2利用多线程完成reader和writer3在main中测试若干个reade......
  • 线程同步-读者写者问题(多线程)
    多线程通信之读者、写者问题读、写问题是另一个非常出名的同步问题,常常用来模拟数据库的数据查询和数据修改两种情况问题。也即,一个数据库允许有多个访问者同时对其进行......
  • WinForm中的多线程
    使用BeginInvoke或Invoke作用在自己创建的非UI线程中,进行UI操作,比如更新UI上控件的状态。Windows窗体中的控件被绑定到特定的线程,不具备线程安全性。因此,如果从另一......
  • 多线程的操作方式
    MAX_PRIOITY10 MIN_PRIOITY 1NORM_PRIOITY 5  getPriority();返回线程的优先级setPriority(intnewPriority)改变线程的优先级......
  • 尚硅谷java入门b站零基础 异常处理 +多线程+部分项目三 2022.3.26
    380如何自定义异常/**如何自定义异常类?*1.继承于现有的异常结构:RuntimeException、Exception*2.提供全局常量:serialVersionUID*3.提供重载的构造器**/publicc......