java多线程

package thread;
//继承Thread类
public class Day1 extends Thread{
//    重写run()方法

    @Override
    public void run() {
        System.out.println("线程运行的代码");
        for (int i = 0; i < 5; i++) {
            System.out.println("这是逻辑代码"+i);

        }
    }
}
/**
 * @author
 * 开启run()方法后,run()方法的执行与mian()方法的执行互不相干,类似河流是俩条支流
 * 控制台的结果是两个方法的总和
 * 这个就是多线程的异步,是相对于start方法来说的,是并行执行没有先后顺序
 */
public class Test {
    public static void main(String[] args) {
        Thread day1 = new Day1();
//        启动
      System.out.println("++++");
        day1.start();
        System.out.println("++++");
        System.out.println("++++");
    }
}
//实现 Runnable接口
public class Test implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程运行的代码");
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName()+"这是逻辑代码"+i);

        }
    }
}

public class Test1 {
    public static void main(String[] args) {
//        通过Thread创建实例
        Thread thread = new Thread(new Test());
        thread.start();

//        追加参数创建对象,这个可以获得线程名称,可以用来区分打印的数据是哪一个线程执行
        Thread thread1 = new Thread(new Test(),"tt");
        thread1.start();
    }
}

并发与并行

并发:指两个或多个事件在同一时间内发生

并行:指两个或多个事件在同一时刻(同时发生)

进程

一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

进程是资源分配的最小单位,线程是程序执行的最小单位(资源调度的最小单位)

进程有自己的独立地址空间,每启动一个进程,系统就会为它分配地址空间,建立数据表来维护代码段、堆栈段和数据段,这种操作非常昂贵。

线程

进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
而线程是共享进程中的数据的,使用相同的地址空间,因此CPU切换一个线程的花费远比进程要小很多,同时创建一个线程的开销也比进程要小很多。

继承与实现的区别

继承:线程代码存放在Thread子类run方法中

实现:线程代码存放在接口的子类run方法

实现方法的好处

避免单继承的局限性

多个线程可以共享同一个接口实现类的对象,非常适合多个线程来处理同一份资源

使用多线程的有点

提高应用程序的响应

提高计算机系统cpu的利用率

改善程序结构

线程的生命周期

线程的同步

package thread;

/**
 * 多线程调用这个方法,线程的资源共享,一个线程执行这个方法没有结束,另一个线程也开始执行了
 *
 *  多线程安全问题:多条语句同时操作一个线程共享数据时,会导致共享数据的错误
 *  解决方法:让一个线程执行结束,再接下一个
 *
 *  通过synchronized同步锁来完成
 *  可以直接在方法上加上这个关键字,这个锁是锁整个对象,不是某一个方法
 *  普通方法加这个关键字就是不同对象就是不同锁,线程使用不同的此方法的对象,还是会出现资源共享问题
 *  静态方法加这个关键字:对于所有对象都是同一个锁
 */
public class Test0 {
    public static void main(String[] args) {
//        定义账户对象
        Acount a = new Acount();
//        定义多线程对象
        Ures ures = new Ures(a,3000);
        Ures ures1 = new Ures(a,3000);
        Thread t = new Thread(ures,"微信");
        Thread t1 = new Thread(ures1,"支付宝");

        t.start();
        t1.start();
    }
}
class Acount{
    public static int money = 3000;
//    同步锁
//   静态同步锁 public statiac synchronized void drawing(int m) {
//    public synchronized void drawing(int m) {
        public  void drawing(int m) {
        synchronized (this){//表示当前对象的代码块被加了同步锁 synchronized (this)的代码块使用的都是同一个同步锁
//            用this锁代码块是代表当前的对象,如果在其他方法中也有
        if (money < m) {
            System.out.println("金额不足" + money);
        } else {
            System.out.println(Thread.currentThread().getName() + "账户原来金额"+money);
            System.out.println(Thread.currentThread().getName() + "取款金额" + m);

            money -= m;
            System.out.println(Thread.currentThread().getName() + "取款后" + money);
        }}
    }
}
class Ures implements Runnable{
    Acount acount;
    int money;
    public Ures( Acount acount,int money){
        this.acount=acount;
        this.money=money;
    }
    @Override
    public void run() {
        acount.drawing(money);
    }
}

在这里插入图片描述

如果针对对象要加同步锁,那就加在方法上

如果针对某一段代码需要加同步锁,那就直接加在代码上

线程的死锁问题

1、不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁。
2、出现死锁后,不会出现异常,不会出现提示,知识所有线程都处于阻塞状态,无法继续。

解决方法

1、专门的算法、原则
2、尽量减少同步资源的定义
3、尽量避免嵌套同步

线程通信

这三个方法只能用在有同步锁的代码块或方法上

package thread;

/**
 *
 */
public class Test0 {
    public static void main(String[] args) {
//        定义账户对象
        Acount a = new Acount();
//        定义多线程对象
        Ures ures = new Ures(a,3000);
        Ures ures1 = new Ures(a,3000);
        Thread t = new Thread(ures,"微信");
        Thread t1 = new Thread(ures1,"支付宝");

        t.start();
        t1.start();
    }
}
class Acount{

    public static int money = 3000;
        public  void drawing(int m,Acount a) {
        synchronized (a){
            //    如果是微信操作的,先不执行,等支付宝操作,支付宝操作完,微信再执行
       
            if ("微信".equals(Thread.currentThread().getName())) {
                try {
                    a.wait();//当前线程进入等待阻塞状态
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        if (money < m) {
            System.out.println(Thread.currentThread().getName()+"金额不足" + money);
        } else {
            System.out.println(Thread.currentThread().getName() + "账户原来金额"+money);
            System.out.println(Thread.currentThread().getName() + "取款金额" + m);

            money -= m;
            System.out.println(Thread.currentThread().getName() + "取款后" + money);
        }
        if ("支付宝".equals(Thread.currentThread().getName())){
            a.notify();//唤醒当前线程优先级最高的,进入就绪状态
         //   a.notifyAll();//唤醒当前所有线程,进入就绪状态
        }
            }
    }
}
class Ures implements Runnable{
    Acount acount;
    int money;
    public Ures( Acount acount,int money){
        this.acount=acount;
        this.money=money;
    }
    @Override
    public void run() {
        acount.drawing(money,acount);
    }
}
posted @ 2022-03-30 19:04  Tzeao  阅读(26)  评论(0)    收藏  举报