多线程

本文介绍了多线程的概念,包括进程、并发与并行的区别,详细讲解了Java中创建线程的三种方式:Thread类、实现Runnable接口和Callable接口。并探讨了线程的并发执行、线程调度、线程同步等问题,同时提供了一个多窗口卖票的程序示例。
摘要由CSDN通过智能技术生成

进程

进程:正在运行的应用程序
我们一个应用程序在运行过程中,会执行不同的任务,那么没一个任务,我们称之为线程
线程要依赖与进程,一个进程至少要有一个线程。
进程是拥有资源的基本单位,线程是CPU调用的基本单位

并发与并行

并发:指的是逻辑上的同时发生

并行:指的是物理上的同时发生

什么是并发 ?
并发 : 指应用能够交替执行不同的任务, 其实并发有点类似于多线程的原理, 多线程并非是如果你开两个线程同时执行多个任务, 执行, 就是在你几乎不可能察觉到的速度不断去切换这两个任务, 已达到
“同时执行效果”, 其实并不是的, 只是计算机的速度太快, 我们无法察觉到而已.就类似于你, 吃一口饭喝一口水, 以正常速度来看, 完全能够看的出来, 当你把这个过程以n倍速度执行时…可以想象一下.

什么是并行 ?
并行 : 指应用能够同时执行不同的任务, 例:吃饭的时候可以边吃饭边打电话, 这两件事情可以同时执行

多线程

什么是线程?

在一个进程内部又可以执行多个任务,而这每一个任务我们就可以看成是一个线程。是程序使用CPU的基本单位。

多线程有什么意义呢?

线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。
多线程的作用不是提高执行速度,而是为了提高应用程序的使用率。
直白话就是通过多线程来抢夺CPU的使用率
Java中多个线程,执行是随机性的,因为我Java采用的线程调度模型是抢占式调度,线程优先级高的优先使用CPU的执行权,优先级一样,就是随机抢占

创建一个接口的三种方式

方式一:Thread类

Thread中的方法

线程类,如果想开启线程,需要创建一个类,继承Thread,重写Thread类中的run方法,创建我们写的这个子类对象,开启线程,让他执行run方法里面的代码。

public void run()

run方法里面的代码就是需要线程来执行的代码,一般我们会在run方法里面进行一些耗时操作。
另外,MyThread myThread = new MyThread(); myThread.run不是开启线程,只是普通的new对象调用方法。

public void start()

开启线程的正确方法,MyThread myThread = new MyThread(); myThread.start();
该线程开始执行,JAVA虚拟机去调用run方法
myThread.start();不能重复开启线程,否则报错。

void setName(String name)

设置线程名称
MyThread th1 = new MyThread();
th1.setName(“刘亦菲”);

public static void sleep(long millis)

让线程休眠一段时间,括号里面是单位是毫秒,是一种阻塞状态。
th1.sleep(1000)等待1秒钟再执行

public void interrupt()

打断线程的阻塞状态,让线程继续运行

public final int getPriority()

返回线程的优先级。

public final void setPriority(int newPriority)

设置线程的优先级。可以设置为1,5,10,Thread.MIN_PRIORITY,Thread.MAX_PRIORITY
th1.setOriority(1)
th1.setOriority(5)
th1.setOriority(10)
th1.setOriority(Thread.MIN_PRIORITY)
th1.setOriority(Thread.MAX_PRIORITY)

public static void yield()

线程礼让

public final void join()

等待该线程执行完毕了以后, 其他线程才能再次执行,
注意事项:在线程启动之后, 在调用方法
MyThread th1 = new MyThread(“张飞”);
MyThread th2 = new MyThread(“关羽”);
th1.start();
th1.join();
th2.start();
th2.join();

public final void setDaemon(Daemon(boolean on)

将该线程标记为守护线程或用户线程,当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。当用户线程,执行完之后,那么守护线程,必须里面死亡。设置为守护线程 该方法必须在启动线程前调用。
MyThread th1 = new MyThread(“张飞”);
MyThread th2 = new MyThread(“关羽”);
th1.setDaemon(true);
th2.setDaemon(true);
th1.start();
th2.start();

方式二:实现Runnable接口

  1. 创建线程的另一种方法是声明实现 Runnable 接口的类。

  2. 该类然后实现 run 方法。然后可以分配该类的实例。

  3. 在创建 Thread 时作为一个参数来传递并启动。

    public class MyTest {
     public static void main(String[] args) {
    
    MyRunable myRunable = new MyRunable();
    
    //Thread(Runnable target)
    //分配新的 Thread 对象。
    
    //Thread(Runnable target, String name)
    //分配新的 Thread 对象。
    Thread th = new Thread(myRunable,"王菲");
    th.start();
    Thread th2 = new Thread(myRunable,"谢霆锋");
    th2.start();
    }
    }
    

	public class MyRunable implements Runnable { //Runable 任务
	 @Override
	public void run() {
    for (int i = 0; i < 100; i++) {
        // System.out.println(this.getName+"==+i");
        System.out.println(Thread.currentThread().getName() + "==" + i);
    }
	  }
	}

方式三:实现 Callable接口

A:
实现 Callable 接口。相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
B:
执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。FutureTask 是 Future 接口的实现类
C:
实现步骤
1. 创建一个类实现Callable 接口
2. 创建一个FutureTask类将Callable接口的子类对象作为参数传进去
3. 创建Thread类, 将FutureTask对象作为参数传进去
4. 开启线程

Callable 返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。
Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

	public static void main(String[] args) throws ExecutionException, InterruptedException {
  

    MyCallable myCallable = new MyCallable();
    FutureTask<Integer> integerFutureTask = new FutureTask<>(myCallable);
    Thread th = new Thread(integerFutureTask);
    th.start();

    //获取线程执行完之后,返回的结果

    Integer integer = integerFutureTask.get();
    System.out.println(integer);


}
}

public class MyCallable implements Callable<Integer> {

//需要线程来执行的方法
@Override
public Integer call() throws Exception {
    System.out.println(Thread.currentThread().getName()+"  aaaaaa");


    return 100;
}
}
编写程序,完成多个窗口共卖100张票的程序,并测试。
			public class Mytest2 {
public static void main(String[] args) {
    CellRunable cellRunable = new CellRunable();
    Thread th1 = new Thread(cellRunable);
    Thread th2 = new Thread(cellRunable);
    Thread th3 = new Thread(cellRunable);
    th1.setName("1号窗口");
    th2.setName("2号窗口");
    th3.setName("3号窗口");
    th1.start();
    th2.start();
    th3.start();
}
}

public class CellRunable implements Runnable{
static int piao = 100;
static Object obj = new Object();
static Lock lock = new ReentrantLock();

@Override
public void run() {
while (true){
    lock.lock();
    if (piao>0){
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "正在售卖 " + (piao--) + " 张票");
    }
    lock.unlock();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值