Java中的多线程

 

目录

一、线程中的基本方法

二、线程的两种实现方法

第一种方法

第二种方法

三、线程睡眠

四、线程礼让

五、线程同步机制


多线程并不是真正意义上的并行执行,而是多个线程交替性抢占CPU资源,
谁获取了CPU资源就执行谁在执行过程中,有可能丢失CPU资源,被另外一个线程执行,所以会出现交替执行的现象。但是以人肉眼无法观察到计算机中的交替执行,故而可以看作为多线程。

一、线程中的基本方法

        //获取线程优先级的最大值/最小值/默认值
        System.out.println(Thread.MAX_PRIORITY);//10
        System.out.println(Thread.MIN_PRIORITY);//1
        System.out.println(Thread.NORM_PRIORITY);//5

        //获取当前正在运行的线程对象
        Thread thread =Thread.currentThread();
        //获取当前线程对象的名称
        String name =thread.getName();
        System.out.println("当前运行线程的名称:"+name);//main
        //获取当前线程的id
        long num =thread.getId();
        System.out.println(num);//1
        //获取当前线程的优先级
        int priorty =thread.getPriority();
        System.out.println(priorty);//5

        //获取当前线程的状态
        Thread.State state =thread.getState();
        System.out.println(state);//RUNNABLE

        //设置线程的名称
        thread.setName("葵花点穴手");
        System.out.println(thread.getName());//葵花点穴手

        //设置线程优先级
        thread.setPriority(8);
        System.out.println(thread.getPriority());//8

        String str = thread.toString();
        System.out.println(str);//Thread[葵花点穴手,8,main]

二、线程的两种实现方法

第一种方法

(1) 第一步:创建MyThread类,继承Thread类

(2)第二步:重写run()方法

(3)第三步;在run()方法中编写线程运行代码

(4)第四步:创建线程类对象,并用start()方法启动线程

第二种方法

(1)第一步;创建MyRunnable类,实现Runnable接口

(2)第二步:重写run()方法

(3)第三步:在run()方法中编写线程运行代码

(4)第四步:创建MyRunnable类对象,由于MyRunnable没有start()方法,所以用Thread将其封装为一个线程对象,再用start()方法启动线程

三、线程睡眠

当当前线程遇到想让其暂停一段时间的条件时,可以使用sleep方法使其睡眠一段时间后再自动运行。

@Override
    public void run() {
        for (int i = 1; i <=10; i++) {
            System.out.println(Thread.currentThread().getName()+":"+i);
            if(i==5){
                try {
                    // 睡眠5秒后执行
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
public static void main(String[] args) {
        MyRunnable3 mr = new MyRunnable3();
        Thread t = new Thread(mr);

        t.start();

    }

四、线程礼让

线程礼让:让当前执行run()方法的线程释放CPU资源,给其它线程一个获得CPU资源的机会,
但是当前线程还会抢占CPU资源,也就是说,当前线程释放CPU资源后,会与其它线程再一次抢占CPU,就看其它线程能不能抓住这个机会。

public static void main(String[] args) {
        MyRunnable5 mr = new MyRunnable5();
        Thread t1 = new Thread(mr, "线程A");
        Thread t2 = new Thread(mr, "线程B");

        t1.start();
        t2.start();

    }
@Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + "正在运行:" + i);
            if (i == 3) {
                System.out.print("线程礼让:");
                Thread.yield();
            }
        }
    }

五、线程同步机制

当多线程并发的环境下,有共享数据,并且这个数据还会被修改,此时就存在线程安全问题,
怎么解决这个问题?
线程排队执行。(不能并发).用排队执行解决线程安全问题。
这种机制被称为:线程同步机制。

此时就需要使用synchronized,synchronized(syncObject)就是为当前的线程声明一把锁

syncObject是同步的对象,一般为this。

多个并发线程访问同一资源的同步代码块时,同一时刻只能有一个线程进入synchronized(this)同步代码块。
当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定。
当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码。

应用:使用synchronized两个取钱线程进行限制,使其无法同时对账户进行取钱,以此来保护线程安全。

    private String actno;
    private double balance;

    public Account() {
    }

    public Account(String actno, double balance) {
        this.actno = actno;
        this.balance = balance;
    }

    public String getActno() {
        return actno;
    }

    public void setActno(String actno) {
        this.actno = actno;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    // 取款方法
    public synchronized void withdraw(double money){
            double before = this.getBalance();
            double after = before-money;
            // 网络延迟,导致两个线程同时进行,不安全
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.setBalance(after);

    }
public class AccountThread extends Thread{
    // 两个线程必须共享同一个账户对象
    private Account act;

    // 通过构造方法传递过来账户对象
    public AccountThread(Account act) {
        this.act = act;
    }

    // run方法执行表示取款操作
    public void run(){
        double money = 5000;

        act.withdraw(money);

        System.out.println(Thread.currentThread().getName()+"对"+act.getActno()+"取款成功,余额:"+act.getBalance());
    }


}
        public static void main(String[] args) {
        // 创建账户对象
        Account account = new Account("act-001",10000);

        // 创建两个线程
        Thread t1 = new AccountThread(account);
        Thread t2 = new AccountThread(account);

        t1.setName("t1");
        t2.setName("t2");


        // 启动线程
        t1.start();
        t2.start();
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值