java多线程

1. 正文

  1. 什么是进程?
  2. 什么是线程?
  3. java如何实现多线程。
  4. Thread类中常见的方法。
  5. 线程安全问题如何解决?
  6. 线程之间的通信?
  7. 线程池

2. 什么是进程?

正在运行的程序就是进程。

进程和线程之间的区别:

  1. 进程是一个正在运行的程序,它是系统分配资源的基本单位。
  2. 线程它是进程中的一个任务,与其他线程可以独立运行。它是cpu调度的单位。多线程是为了充分利用cpu资源。提高效率。

3. java中如何创建多线程

3.1 继承Thread来完成多线程

public class MyThread extends Thread {//Thread:表示线程类
    //重写run方法: 当线程启动时,会调用run方法体中的代码
    @Override
    public void run() {
       for (int i=0;i<20;i++){
           System.out.println("线程==============="+i);
       }
    }
}

3.2 获取和设置线程的名称

1691996101798

package demo01;

public class MyThread extends Thread {//Thread:表示线程类
    //重写run方法: 当线程启动时,会调用run方法体中的代码
    @Override
    public void run() {
       for (int i=0;i<20;i++){
           //this.getName()获取当前线程的名称。---该方法只能用在Thread子类下
           //System.out.println(this.getName()+"线程==============="+i);

           //该方法可以在任意位置获取线程名: 默认系统会为每个线程--Thread-n:
           System.out.println(Thread.currentThread().getName()+"=========="+i);
       }
    }
}
package demo01;

public class Test {
    public static void main(String[] args) {
        //1.创建一个线程对象
        MyThread m01=new MyThread();
        m01.setName("线程A"); //为线程对象起名称
        MyThread m02=new MyThread();
        m02.setName("线程B");
        //2.开启线程.start()---底层会自动调用线程的run方法,来执行该线程的任务
        m01.start();
        m02.start();

        for(int i=0;i<20;i++){         System.out.println(Thread.currentThread().getName()+"~~~~~~~~~~"+i);
        }
    }
}

3.3 案例

package demo02;

public class MyTicketTask extends Thread {
    //卖100张票
    @Override
    public void run() {
         while(ticket>0){
             ticket--;
             System.out.println(Thread.currentThread().getName()+"卖了一张票:剩余:"+ticket+"张");
         }
    }
}
public class Test {
    public static void main(String[] args) {
        MyTicketTask t01=new MyTicketTask();
        t01.setName("窗口1");
        MyTicketTask t02=new MyTicketTask();
        t02.setName("窗口2");
        MyTicketTask t03=new MyTicketTask();
        t03.setName("窗口3");
        MyTicketTask t04=new MyTicketTask();
        t04.setName("窗口4");

        t01.start();
        t02.start();
        t03.start();
        t04.start();
    }
}

3.4 实现Runnable接口

1691998073392

你会选中Thread还是Runnable形式:

java只允许单继承,但是可以实现多个接口。 选择第一种继承Thread方式,那么他就无法继承别的类,不利于扩展。

3.5 案例

出现了超卖和重卖: 这是因为线程安全问题。----解决线程安全问题。

1691999018051

4. Thread线程类中常用的方法

1692001880519

1692002459816

5. 线程安全问题

前面我们卖票系统---出现线程安全问题。 解决线程安全问题。

当多个线程共享一个资源时,可能会出现线程安全问题。

如何解决线程安全问题? ----使用锁。--->凡是用锁 锁定的代码都是原子操作。

第一种自动锁: synchronized

第二种手动锁: Lock

public class TicketTask implements Runnable {
    private int ticket = 100;
private Lock l=new ReentrantLock();//创建手动锁对象
    public void run() {
        while (true) {
//            synchronized (this) { //自动上锁和释放锁。
//                if (ticket > 0) {
//                    ticket--;
//                    System.out.println(Thread.currentThread().getName() + "卖了一张票;剩余:" + ticket + "张");
//                } else {
//                    break;
//                }
//            }
            l.lock();//手动上锁
            if (ticket > 0) {
                    ticket--;
                    System.out.println(Thread.currentThread().getName() + "卖了一张票;剩余:" + ticket + "张");
                } else {
                    break;
                }
            l.unlock();//手动释放锁

        }
    }
}
posted @ 2023-08-15 09:42  知行合二为一  阅读(46)  评论(0编辑  收藏  举报