Java中的多线程

Java中的多线程

多线程的最主要的目的:是为了提高程序的执行效率(不是执行速度),提高CPU的利用率,如果两个方法之间不存在因果调用关系,那么可以考虑在一个方法执行时开辟另一个线程执行另一个方法,而不用等第一个方法执行完之后再执行第二个方法

计算机通常会有多个核心,一个核心在同一个时间点(很小的计量单位)只能有一个程序在运行。CPU会在高速的情况下,不断的进行切换。线程是一个进程内的独立的执行单元(一个进程至少包含一个线程)。

多线程的实现方案

创建新执行线程有两种方法。

  • 但最终都是使用start()方法来启动新线程,

1. 一种方法是将类声明为 Thread 的子类。

该子类应重写 Thread 类的 run 方法。

  • 一个类只能调用一次start()方法
  • 线程可以指定名字
    • 默认无参的构造方法,会产生默认的名字。
    • 构造时传递名字 public final String getName(),使用getname()方法获取线程名称
      在这里插入图片描述

代码实现:

	class MyThread extends Thread{
		@Override
		public void run() {
		//方法体中的代码,就是你将在新的线程中执行的代码内容.
		System.out.println("这是子线程中干的事情");
		}
	}
		public class TestThread {
		    public static void main(String[] args) {
		        MyThread myThread = new MyThread();
		        myThread.start();
		    }
		}
		
		class MyThread extends Thread{
		    @Override
		    public void run() {
		        System.out.println("新线程");
		    }
		}

线程休眠 sleep()

public class TestThread {
    public static void main(String[] args) {
        MyThread myThread = new MyThread("线程一");
        System.out.println(myThread.getName());
        
        try {
            myThread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread.start();
    }
}

class MyThread extends Thread{

    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(this.getName());
    }
}

2. 实现 声明Runnable 接口的类

Runnable 接口中只有一个run方法,优点是解决当一个类继承了Thread后无法继承其他类的问题
使用方法:

  • 实现Runnable接口
  • 重写run()方法
  • 创建runnable实例
  • 创建Thread实例
  • 将Runnable实例放入Thread实例中
  • 通过线程实例控制线程的行为(运行,停止),在运行时会调用Runnable接口中的run方法。

获取线程名称:Thread.currentThread().getName()详见4.2实现Runnable接口卖票

3.(有一点问题,不确定Runnable中是否开了多个线程)彻底理解Runnable和Thread的区别

4.多线程卖票案例

4.1继承Thread类卖票

存在重复卖票和,0票和负票的情况
重复票:使用了count = count-1; 应该使用count–;
负票: 在一个线程进行的过程中,如果休眠了,计算机调用另一个线程开始,票数为1条件满足,线程二进入休眠,此时线程一开始卖票并更新票数为0,线程二卖票时就卖出了0票,当还有线程时就会卖出负票。

0票和负票的解决是使用锁,在一个线程进行的时候,对count上锁,暂时禁止共享,用到的是同步代码块

同步代码块(锁)
如果发现没有锁住想要的,那么一定是多个线程之间锁的对象Object不一致

Synchronized(锁对象){
	需要同步的代码块
}

卖票的代码具体实现

public class MaiPiao {

    public static void main(String[] args) {

        MyThread mythread1 = new MyThread("窗口一");
        MyThread mythread2 = new MyThread("窗口二");
        MyThread mythread3 = new MyThread("窗口三");
        Mythread1.start();
        Mythread2.start();
        Mythread3.start();

    }
}

class MyThread extends Thread {
	//这里必须是静态变量,让线程可以共享修改变量
    static int total = 100;
    //对象也必须是静态的,否则synchronized锁的不是同一个对象
    private static Object lockobject = new Object();

    public myThread(String name) {
        super(name);
    }

    @Override
    public void run() {
         synchronized (lockobject){
            while ( total>0) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(this.getName()+"卖出第"+(total--)+"张票");
            }

        }
        }
}

4.2实现Runnable接口卖票

用到了同步方法
当一个方法都要用synchronized锁起来时可以不用创建新对象,直接在方法前加synchronized关键字修饰

public class TestRunable {
    public static void main(String[] args) {
        //实例化MyRunnable对象
        MyRunnable myRunnable = new MyRunnable();

        //实例化Thread对象,即线程
        Thread thread1 = new Thread(myRunnable,"线程一");
        Thread thread2 = new Thread(myRunnable,"线程二");
        Thread thread3 = new Thread(myRunnable,"线程三");

        //启用线程
        thread1.start();
        thread2.start();
        thread3.start();


    }
}
class MyRunnable implements Runnable{
    static  int count = 100;
    
    @Override
    //同步方法
    public synchronized void run() {

        while (count >0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"卖出第"+(count--)+"张票");
        }

    }
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值