多线程的初步了解

多线程

基本概念:

在多线程中有许多基本概念,因此我们先对每个概念做出解释。

进程:

操作系统中独立的运行程序,如QQ,音乐播放器等。

进程的特性:

  1. 独立性。每个进程之间是相互独立的、互不影响的。
  2. 互斥性。每个进程(程序)系统都会分配一个独立的端口号,一旦该端口号被占用,那么其他进程就无法使用该端口号。
线程:

进程是由一个或者多个线程组成的,每个进程至少有一个线程支撑。一个线程就是一个小的功能,程序就是由一个个功能组成的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vK7vfe7i-1660123117683)(day作业22.assets/image-20220810162341700.png)]

线程的特性:

  1. 抢占式运行。CPU在执行的时候,是按照时间片来执行的,在单位时间片内,多个线程抢占,谁抢到这个时间片就属于谁。
  2. 资源共享。一个线程可以共享当前CPU、网卡等。
并行:

同时发生,轮流交替执行。

并行指两个或两个以上事件或活动在同一时刻发生,在多道程序环境下,并行使多个程序同一时刻可在不同CPU上同时执行。

并发:

真正意义上的同时执行。

并发是在同一个cpu上同时(不是真正的同时,而是看来是同时,因为CPU要在多个程序之间切换)运行多个程序。

创建线程的两种方式:
方式1:继承Thread类

步骤:

1、创建一个普通类去继承Thread类

2、然后重写run方法

3、实例化该子类,并启动线程

package com.lyc.lesson;

class MyThread extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("吃毛血旺");
        }
    }
}
class MyThread1 extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("吃水煮肉片");
        }
    }
}

public class Lesson01 {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        MyThread1 myThread1 = new MyThread1();
        myThread.start();
        myThread1.start();;
        for (int i = 0; i < 10; i++) {
            System.out.println("吃大盘鸡");
        }
    }
}

方式2:实现Runable接口

步骤:

1、创建一个普通类去实现Runable接口

2、子类中实现run方法。

3、实例化子类

4、new一个Thread的对象,将实例化子类作为参数传递,并启动。

package com.lyc.lesson;

class MyThread3 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("线程三:"+i);
        }
    }
}

class MyThread4 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println("线程四:"+i);
        }
    }
}
public class Lesson02 {
    public static void main(String[] args) {
        MyThread3 myThread3 = new MyThread3();
        MyThread4 myThread4 = new MyThread4();
        Thread thread = new Thread(myThread3);
        Thread thread1 = new Thread(myThread4);
        thread.start();
        thread1.start();
        for (int i = 0; i < 50; i++) {
            System.out.println("主线程一:"+i);
        }
    }
}

线程中的方法:
static ThreadcurrentThread()返回对当前正在执行的线程对象的引用
StringgetName()返回此线程的名称。
voidsetName(String name)将此线程的名称更改为等于参数 name
intgetPriority()返回此线程的优先级。
voidsetPriority(int newPriority)更改此线程的优先级。
设置优先并不一定优先,只是增加了执行的概率。最小值是1,最大值是10,默认的是5
static voidsleep(long millis)使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

方法的实现案例:

package com.lyc.lesson;

class MyThread5 implements Runnable{
    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        thread.setName("这是一个重命名的线程");
        System.out.println(thread.getName());
        System.out.println(thread.getPriority());
    }
}
public class Lesson03 {
    public static void main(String[] args) {
        Thread thread1 = Thread.currentThread();  //获取线程对象
        System.out.println(thread1.getPriority());  //获取线程优先级
        System.out.println(thread1.getName());   //获取线程名字

//        MyThread5 myThread5 = new MyThread5();
//        Thread thread2 = new Thread(myThread5);
//        Thread thread = new Thread(new MyThread5());
        new Thread(new MyThread5()).start();

    }
}

sleep()方法:

package com.lyc.lesson;

class MyThread8 implements Runnable{

    @Override
    public void run() {
        Thread thread = Thread.currentThread();
        thread.setName("这是已经睡眠过的线程");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName()+":"+i);
        }
    }
}

public class Lesson05 {
    public static void main(String[] args) {
        new Thread(new MyThread8()).start();
        Thread thread = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            System.out.println(thread.getName()+":"+i);
        }
    }
}

线程的同步和锁:

为什么要进行线程的同步?

Java是允许多线程的,当多个线程操作同一个资源的时候,就会导致得到的或打印的数据不准确。从而发生冲突。

如下案例:

三个窗口买一百张电影票。

package com.lyc.lesson;

class MySync implements Runnable{
    int ticket = 100;
    @Override
    public void run() {
        while (true){
            if (ticket >0){
                System.out.println(Thread.currentThread().getName()+":"+ticket+"张票");
                ticket--;
            } else {
                System.out.println("买完了");
                break;
            }
        }
    }
}

public class Lesson07 {
    public static void main(String[] args) {
        MySync mySync = new MySync();
        Thread thread = new Thread(mySync,"窗口1:");
        Thread thread1 = new Thread(mySync,"窗口2:");
        Thread thread2 = new Thread(mySync,"窗口3:");

        thread.start();
        thread1.start();
        thread2.start();
    }
}

输出结果:

以我们一般的思维来讲,当一个窗口的票卖出去一张票后,其他窗口应该从剩余的票开始卖,但是结果却不是这样,这时就是线程的同步问题。那么该如何解决?加同步锁。

同步代码块:

同步代码块:就是拥有了synchronized 关键字修饰一个语句块。被修饰的语句块会被加锁。从而实现同步。语法格式如下:

synchronized  (this) {
	被加锁的代码块
}

对上述案例进行修改:

package com.lyc.lesson;

class MySync implements Runnable{
    int ticket = 100;
    @Override
    public void run() {
        while (true) {
            //同步锁
            synchronized (this) {
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + ":" + ticket + "张票");
                    ticket--;
                } else {
                    System.out.println("买完了");
                    break;
                }
            }
        }
    }
}

public class Lesson08 {
    public static void main(String[] args) {
        MySync mySync = new MySync();
        Thread thread = new Thread(mySync,"窗口1:");
        Thread thread1 = new Thread(mySync,"窗口2:");
        Thread thread2 = new Thread(mySync,"窗口3:");

        thread.start();
        thread1.start();
        thread2.start();
    }
}

输出结果:

我们对循环进行加锁,这样就能保证在对数据进行操作时,只能是一个线程,谁抢到谁就操作数据,其他线程只能等待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值