ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java基础之十七->多线程

2021-09-21 09:32:38  阅读:199  来源: 互联网

标签:ticketRunnable 十七 java Thread start 线程 new 多线程 public


一、线程基础内容

1、程序、进程与线程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、程序:Program,是一个指令的集合
2、进程:Process,(正在执行中的程序)是一个静态的概念

进程是程序的一次静态执行过程,占用特定地的地址空间
每个进程都是独立的,由3部分组成cpu,data,code
缺点:内存的浪费,cpu的负担

3、线程:是进程中一个“单一的连续控制流程”/执行路径

线程又被成为轻量级进程
Threads run at the same time,independently of one another
一个进程可拥有多个并行的线程
一个进程中的线程共享相同的内存单元/内存地址空间->可以访问相同的变量和对象,而且他们从同一堆中分配对象->通信、数据交换、同步操作
由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得通信更简便而且信息的传递速度也更快

2、线程的创建和启动

2.1、第一种方式

在这里插入图片描述
继承Thread类,重新run方法,调start(启动线程),每次运行相同的代码,出来的结果可能不一样,原因在于多线程谁先抢占资源无法进行认为控制

package com.msbline.threadPkg;
public class ThreadDemo extends Thread{
    @Override
 public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() +"---"+ i);
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        threadDemo.start();
        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() +"==="+ i);
        }
    }
}
2.2、第二种方式

在这里插入图片描述
实现Runnable接口,重写run方法,创建Thread对象,将刚刚创建好的Runnable的子类实现作为Thread的构造参数,通过Trhead.start()进行启动

package com.msbline.threadPkg;
public class ThreadDemo02 implements Runnable{
    @Override
 public void run() {
        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() +"---"+ i);
        }
    }
    public static void main(String[] args) {
        ThreadDemo threadDemo = new ThreadDemo();
        new Thread(threadDemo).start();
        for (int i = 0; i < 10; i++){
            System.out.println(Thread.currentThread().getName() +"==="+ i);
        }
    }
}
两种方式哪种使用更多

在这里插入图片描述
在这里插入图片描述

3、线程的生命周期

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、线程的代理设计模式

在这里插入图片描述

5、线程操作的相关方法

在这里插入图片描述

1、sleep 方法是属于 Thread 类中的,sleep 过程中线程不会释放锁,只会阻塞线程,让出cpu给其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态,可中断,sleep 给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会

2、yield和 sleep 一样都是 Thread 类的方法,都是暂停当前正在执行的线程对象,不会释放资源锁,和 sleep 不同的是 yield方法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只需要等待重新获取CPU执行时间,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。还有一点和 sleep 不同的是 yield 方法只能使同优先级或更高优先级的线程有执行的机会

3、join,等待调用join方法的线程结束之后,程序再继续执行,一般用于等待异步线程执行完结果之后才能继续运行的场景。例如:主线程创建并启动了子线程,如果子线程中药进行大量耗时运算计算某个数据值,而主线程要取得这个数据值才能运行,这时就要用到 join 方法了

4、wait 方法是属于 Object 类中的,wait 过程中线程会释放对象锁,只有当其他线程调用 notify 才能唤醒此线程。wait 使用时必须先获取对象锁,即必须在 synchronized 修饰的代码块中使用,那么相应的 notify 方法同样必须在 synchronized 修饰的代码块中使用,如果没有在synchronized 修饰的代码块中使用时运行时会抛出IllegalMonitorStateException的异常

二、线程同步

1、线程同步的必要性

在这里插入图片描述
在这里插入图片描述
多个线程访问同一个共享数据的时候,会出现数据安全问题,比如买票,两个线程同时对一张票进行操作,可能会导致重票的问题

2、线程同步的实现

2.1、同步代码块

synchronized(共享资源,共享对象,需要是Object的子类){具体执行的代码块}

public class TicketRunnable2 implements Runnable{
    private int ticket = 5;
    @Override
 public void run() {
        for(int i = 0; i<100; i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (this){
                if(ticket > 0){
                    System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"票");
                }
            }
        }
    }
    public static void main(String[] args) {
        TicketRunnable2 ticketRunnable = new TicketRunnable2();
        Thread t1 = new Thread(ticketRunnable,"A");
        Thread t2 = new Thread(ticketRunnable,"B");
        Thread t3 = new Thread(ticketRunnable,"C");
        Thread t4 = new Thread(ticketRunnable,"D");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}
2.2、同步方法
public class TicketRunnable3 implements Runnable{
    private int ticket = 5;
    @Override
 public void run() {
        for(int i = 0; i<100; i++){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.sale();
        }
    }
    /**
 * 使用同步方法解决
 */
 public synchronized void sale(){
        if(ticket > 0){
            System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"票");
        }
    }
    public static void main(String[] args) {
        TicketRunnable3 ticketRunnable = new TicketRunnable3();
        Thread t1 = new Thread(ticketRunnable,"A");
        Thread t2 = new Thread(ticketRunnable,"B");
        Thread t3 = new Thread(ticketRunnable,"C");
        Thread t4 = new Thread(ticketRunnable,"D");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

3、死锁

在这里插入图片描述

4、线程同步小结

在这里插入图片描述

三、线程间通信

1、线程间通信的必要性

在这里插入图片描述
一般来说,每个线程自己完成自己的任务就可以了,但有时候,线程的处理会依赖另一个线程的数据,所以就需要线程间通信,来达到同步信息的效果。

2、线程间通信的实现

参考:https://blog.csdn.net/jisuanji12306/article/details/86363390

标签:ticketRunnable,十七,java,Thread,start,线程,new,多线程,public
来源: https://blog.csdn.net/qq_22717543/article/details/120395032

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有