首页 > 其他分享 >线程最全面总结

线程最全面总结

时间:2024-06-18 12:32:19浏览次数:20  
标签:总结 Runnable run Thread 子类 线程 全面 public

多线程开发:并发编程

多线程程序的好处:提高程序的效率


多线程程序如何开发?
方式1 : Thread类(java语言提供的现成的线程类)
    1. 创建一个子类,继承Thread类    (创建的子类:也是线程类)
    2. 在子类中,编写让线程帮助完成的任务(任务代码)
         //重写Thread类中的run方法(线程任务)
    3. 启动线程

    弊端:类只能单一继承
    public class 子类 extends Father  {  //问题:还能在继承Threa类吗?
    }


方式2 :Runnable接口 (接口可以多实现,而且允许子类在继承其他父类)  【推荐 : 灵活度高】
    1. 创建一个子类, 实现Runnable接口
    2. 在子类中,重写Runnable接口中的方法:run  (线程任务方法)
    3. 创建Thread类对象, 并把实现了Runnable接口的子类对象,作为参数传递给Thread类对象
        new Thread(  Runnable类型的对象   )
    4. 启动线程



多线程程序的开发方式:
方式1 :Thread
1. 创建子类,继承Thread类 (不能在继承其他父类了)
2. 子类中重写run方法  (线程任务)
2. 创建子类对象,调用start方法(启动线程)

//线程任务、线程功能     全部都在Thread子类中

方式2 : Runnable
1. 创建子类 ,实现Runnable  (可以继承其他父类)
2. 重写run方法 (线程任务)
3. 创建Thread类对象, 并指定要执行的线程任务(Runnable实现类对象作为参数,传递到Thread类的构造方法中)
4. Thread类对象.start()  (启动线程)

//线程任务 : Runnable接口实现类
//线程功能 : Thread类
推荐使用Runnable接口的方式,好处:解耦

接口的作用:
1. 制定规则
2. 可以降低耦合  (耦合:紧密连接的程度)   //程序都是要求低耦合




并发编程
-- 什么是并发编程
   在一个程序中开启多个线程,让多个线程执行相同的任务,从而提高程序执行效率。

-- 并发编程解决程序中的什么问题
   提高程序的运行效率、提高使用者体验

-- 并发编程怎么写
   1、Thread类
   2、Runnable接口







在Java程序中运行的线程都有属于自己的名字。
例:main方法,就代表主线程(线程名字:main)
   新线程名字: Thread-0 、Thread-1、............

String  getName()  //获取线程的名字
void  setName(String name) //给线程设置一个名字


static  Thread   currentThread() //获取当前正在运行的线程对象


static  void  sleep(long 毫秒)  //让当前运行的线程休息(单位 :毫秒)

void join()  //挂起其他线程,仅当前线程运行




发生线程安全问题的原因: 多个线程对同一个数据,进行读写操作,造成数据错乱


线程安全问题的解决思想: 把多个线程操作的共享数据,存放到一个安全的环境中
java语言基于线程安全问题,提供了:同步机制

同步:
1. 同步代码块
2. 同步方法
3. Lock锁



同步方法:
    修饰符号 synchronized 返回值类型  方法名(参数列表){
    }

    同步方法也有对象锁:
    1. this锁  (当前对象锁)
    2. 类名.class (静态方法上的对象锁)


并行和并发

并行:在同一时刻,有多个任务在多个cpu上同时去进行

并发:在同一时刻,有多个任务在一个cpu上去执行

进程简单地说就是在多个任务操作系统中,每个独立执行的程序

线程是程序进行地基本执行单元

多线程是指从软件或者是硬件上实现的多个线程地并发执行地技术

具有多线程能力地计算机因有硬件的支持而能够在同一时间执行多个线程,提升了性能

例如迅雷就是一种多线程的下载方式

创建一个子类,继承Thread类 (创建的子类:也是线程类)

重写这个Thread的run方法

启动线程

cpu就会在主线程和新线程中高速交换执行

package thread;

/**
 * @author xiaowang
 * @creat 2024/6/14 18:52
 * @Description Java Lotus
 */
public class ThreadDemo1 {
    public static void main(String[] args) {

        System.out.println("进入main方法进行执行");
        MyThread myThread=new MyThread();
        myThread.start();

        for (int i = 0; i <1000 ; i++) {
            System.out.println(i);
        }
    }
}




package thread;

/**
 * @author xiaowang
 * @creat 2024/6/14 18:52
 * @Description Java Lotus
 */
public class MyThread extends Thread{
    //需要当前线程去完成一个任务
    @Override
    public void run(){
        System.out.println("新的线程开始执行");
        for (int i = 100; i <2000 ; i++) {
            System.out.println("新线程"+i);
        }
    }

}

线程的使用:Runnable接口

类只能单一继承

我们现在已经继承类一个父类了,如果还是想再去继承一个类的时候,我们是无法做到的,所以,这个就是runnable接口的引入的问题场景

接口是可以多实现的,并且还可以让子类去继承其他的类

推荐,他的灵活度特别高

创建一个子类,实现一个runnable接口

在子类中,重写这个runnable接口中的方法run (线程任务方法)

创建Thread类对象,并把实现了runnable接口的子类对象

作为参数传递给Thread类对象

package thread.project2;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:11
 * @Description Java Lotus
 */
public class ThreadDemo {
    public static void main(String[] args) {

        System.out.println("进入到主线程中执行方法");
        MyTask task =new MyTask();

        Thread thread = new Thread(task);

        thread.start();

        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
    }
}


package thread.project2;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:10
 * @Description Java Lotus
 */
public class MyTask implements Runnable{

    @Override
    public void run() {
        System.out.println("新线程方法开始执行");
        for (int i = 100; i <200 ; i++) {
            System.out.println("新线程"+i);

        }
    }
}

第一种:方式一,实现多线程

Thread

创建一个子类,继承Thread类

子类中重写run方法

创建子类对象

方式2:Runnable

创建一个子类,实现runnable方法,是一个接口,是可以去继承其他父类的

创建一个Thread类对象,并且指定去执行的线程任务

(Runnable实现对象作为参数,传递到Thread类的构造方法)

  

回顾:线程的使用

并发编程

--什么是并发编程呢

        在一个程序中开启多个线程,让多个线程执行相同的一个任务,从而提高的程序执行效率

--并发编程解决了程序中的什么问题

        提高了效率和使用者的体验

并发编程怎么写

package thread.project3;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:26
 * @Description Java Lotus
 */
public class TheadTask1 extends Thread{
    @Override
    public void run(){
        for (int i = 100; i <200 ; i++) {
            System.out.println(i);

        }
    }
}


package thread.project3;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:27
 * @Description Java Lotus
 */
public class Test1 {
    public static void main(String[] args) {
        TheadTask1 task1 =new TheadTask1();
        task1.start();


        for (int i = 100; i <200 ; i++) {
            System.out.println("main方法"+i);

        }
    }
}



package thread.project3;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:30
 * @Description Java Lotus
 */
public class ThreadTask2 implements Runnable{

    @Override
    public void run() {
        for (int i = 100; i <200 ; i++) {
            System.out.println(i);

        }
    }
}



package thread.project3;

/**
 * @author xiaowang
 * @creat 2024/6/14 19:30
 * @Description Java Lotus
 */
public class Test2 {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            for (int i = 100; i <200 ; i++) {
                System.out.println(i);

            }
        });
        thread.start();
        for (int i = 100; i <200 ; i++) {
            System.out.println("main方法"+i);

        }
    }
}


线程中的常用方法

线程安全问题

多个线程对同一个数据重写操作所产生的错乱,对同一个数据进入读和写

程序是不可以去控制cpu的

线程安全问题解决思路

多线程对同一个数据进行读写操作

同步代码块

1.同步代码块:

2.同步方法:

3.lock锁

使用同步锁以避免在该程序完成操作之前,被其他线程的调用,从而保证该变量额唯一性和准确性

synchronized(同步锁)

多个线程要去使用同一把锁

package com.itheima.thread.security.demo2;

//线程任务类
public class Ticket implements Runnable {
    //成员变量(电影票数)
    private int ticketCount = 100;//有100张电影票

    //锁对象(任意类型对象)
    Object lock = new Object();

    @Override
    public void run() {
            //模拟卖票
            while (true) {
                //使用同步代码块,解决线程安全问题
                synchronized (lock) {
                if (ticketCount <= 0) {
                    break;
                }

                if (ticketCount > 0) {
                    // 模拟出票的时间
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + " 出售票号:" + ticketCount);
                    ticketCount--;
                }
            }
        }
    }
}
package com.itheima.thread.security.demo3;

//线程任务类
public class Ticket implements Runnable {
    //成员变量(电影票数)
    private int ticketCount = 100;//有100张电影票

    @Override
    public void run() {
        //模拟卖票
        while (true) {
            if (ticketCount <= 0) {
                break;
            }
            method();
        }
    }

    //同步方法 (方法中所有的代码都是同步代码)
    private synchronized void method() {
        if (ticketCount > 0) {
            // 模拟出票的时间
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + " 出售票号:" + ticketCount);
            ticketCount--;
        }
    }
}



package com.itheima.thread.security.demo4;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//线程任务类
public class Ticket implements Runnable {
    //成员变量(电影票数)
    private int ticketCount = 100;//有100张电影票

    //Lock锁对象
    Lock l = new ReentrantLock();

    @Override
    public void run() {
        //模拟卖票
        while (true) {
            //使用Lock锁解决线程安全问题
            //获取锁
            l.lock();
            if (ticketCount <= 0) {
                break;
            }
            if (ticketCount > 0) {
                // 模拟出票的时间
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + " 出售票号:" + ticketCount);
                ticketCount--;
            }
            //释放锁
            l.unlock();
        }
    }
}

lock锁

kock和unlock两个方法

线程的死锁

理解线程死锁的条件

互相使用双方的两个锁

死锁是在程序中没办法通过程序去解决的

在程序两个线程中不用交叉使用锁

同步代码块的锁进行了嵌套的使用,就大概率会产生死锁

不要去使用嵌套锁

线程的6种状态

线程的生命周期

new-   创建线程对象

runnable - start方法

blocked- 无法获得锁对象

waiting - wait方法

timed——waiting sleep方法

terminated  全部代码运行完毕

线程状态

标签:总结,Runnable,run,Thread,子类,线程,全面,public
From: https://blog.csdn.net/Darling912/article/details/139688169

相关文章

  • 【线程基础】【七】UncaughtExceptionHandler 的使用
    1 前言我们平时在Java中处理异常的时候,通常的做法是使用try-catch-finally来包含代码块,但是Java自身还有一种方式可以处理就是使用UncaughtExceptionHandler,本节我们就来看看。2  UncaughtExceptionHandler2.1 认识当JVM检测出某个线程由于未捕获的异常而终结的情况......
  • 进行一个字符串算法的总结
    本文参考字符串基础byAlex_Wei。Manacher算法这玩意是用来求回文子串的。虽然一个字符串的子串数量是\(O(n^2)\)级别的,但是回文串有更好的描述方式。注意到若一个子串\([l,r]\)是以\(mid\)为回文中心的回文串,那么将左端点和右端点朝着\(mid\)方向挪动若干单位也......
  • 面经梳理-java多线程同步协作
    题目Synchronized和ReentryLock锁锁可以视作访问共享数据的许可证。锁能够保护共享数据以实现线程安全,其作用包括保障原子性、保障可见性和保障有序性。Java平台中的锁包括内部锁(IntrinsicLock)和显式锁(ExplicitLock)。内部锁是通过synchronized关键字实现的;显式锁是通过java.ut......
  • 面经梳理-java多线程其他
    题目Threadlocal使用场景?原理?如何保证内存不泄露?ThreadLocal使用场景不加锁的情况下,多线程安全访问共享变量,每个线程保留共享变量的副本(线程特有对象),每个线程往这个ThreadLocal中读写是线程隔离。ThreadLocal原理Thread类有一个类型为ThreadLocal.ThreadLocalMap的实例变量th......
  • 面经梳理-java多线程基础
    题目线程和进程的概念?守护线程是干什么的?常见的守护线程有哪些?线程和进程的概念进程是程序的运行实例,是程序向操作系统申请资源的基本单位,线程是进程的一条执行路径。Java的线程分为两种:用户线程和守护线程。守护线程作用是为其他线程提供服务,如果所有的用户线程死亡,后台线程......
  • 第8周总结
    第8周总结:本周,我继续开发地铁查询系统的安卓端。根据Web端的功能和用户反馈,我设计并实现了安卓端的查询和显示功能。通过使用安卓的RecyclerView和Adapter,我实现了数据的动态加载和显示,并结合SQLite数据库存储和管理用户数据。在界面设计上,我尽量保持与Web端一致,以提供统一的用户......
  • 第2周总结:
    第2周总结:本周,我继续深入学习安卓开发知识,并开始着手编写个人作业。重点学习了安卓四大组件(Activity、Service、BroadcastReceiver、ContentProvider)的基本使用方法,尤其是Activity的生命周期和Intent的传递机制。同时,我开始设计并编写一个简单的安卓应用,实现基本的增删改查(CRUD)功......
  • 持续总结中!2024年面试必问 20 道设计模式面试题(二)
    上一篇地址:持续总结中!2024年面试必问20道设计模式面试题(一)-CSDN博客三、请描述单例模式(SingletonPattern)及其使用场景。单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种模式在软件系统中非常常见,因为它提供了一种控制实......
  • 第1周总结
    第1周总结本周,我开始了安卓开发知识的学习,重点集中在基础概念和环境配置上。我通过阅读官方文档和观看视频教程,掌握了安卓开发的基本原理和流程。安装和配置了安卓开发环境,包括AndroidStudio的下载和安装、JDK的配置以及模拟器的设置。通过编写简单的HelloWorld应用,熟悉了安卓......
  • 复习加总结
    Markdown学习标题三级标题四级标题字体粗体:俩*hello,World斜体:一个**hello,World*斜体加粗三个*hello,World删除线:两个~hello,World引用始作俑者没有受罚,仅仅是受害者再受害一次罢了,最多也就是管理/梦境支配者的人类在人类世界的走狗棋子被带走,毫无意义。大于号>分割......