栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程的基本知识

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程的基本知识

一、基本知识

并发:在一个时间段内,高速度切换同时处理多个任务.

并行:指多个任务同时处理.

进程:一段程序的执行过程,他代表了程序所占用的内存区域,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。一个程序中至少有一个进程,一个进程中包含多个线程.

 线程调度:

①分时调度:所有线程轮流使用cpu的使用权.

②抢占调度:优先级高的线程使用cpu时间相对较多.

        分为1到10级,最低1级,最高10级,默认5级

 主线程:执行main方法的线程.

二、Thread类

1、线程5种状态:

①新建状态(New):创建了一个线程对象。

②就绪状态(Runnable):调用了该对象的start()方法。

③运行状态(Running):就绪状态的线程获取了CPU执行权

④阻塞状态(Blocked):线程因为某种原因放弃CPU使用权,暂时停止运行

⑤死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期  

2、阻塞状态:

①等待阻塞:运行状态中的线程wait()方法,JVM会把该线程放入到等待队列中,使本线程进入到等待阻塞状态

②同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),则JVM会把该线程放入锁池中,线程处于同步阻塞状态

③其他阻塞:通过调用线程的sleep()或join()或发出I/O请求时,线程会进入到阻塞状态

3、创建线程的方法一

①创建一个Thread类的子类

②在子类中重写run()方法,在方法内部设置进程任务.

③创建子类对象,调用Thread中start()方法,开启新线程//十大特

缺点:一个类只能继承一个父类,继承了Thread意味着不能继承其他类了,使用接口的方法有效避免了该缺点.

注意事项:结果是两个线程并发运行,多次启动一个线程是违法的,特别是当线程结束执行后,不能在启动.

匿名内部类例子:

new Thread(){

            @Override

            public void run() {

                System.out.println(Thread.currentThread().getName());

            }

        }.start();

4、创建线程的方法二

①创建Runnable 接口的实现类.//ruang 呢包

②在实现类中重写run()方法.

③创建实现类的对象.

④创建Thread对象参数传入实现类的对象,并调用start()方法.

注意事项:①Thread中有个构造方法Thread(Runnable target) 传入的参数类型为Runnable类

②以上两个方法可以使用匿名内部类创建. 

匿名内部类例子:

new Thread(new Runnable(){

            @Override

            public void run() {

                System.out.println(Thread.currentThread().getName());

            }

        }).start();

5、Thread成员方法

static Thread

currentThread() //可润特 //返回对当前正在执行的线程的对象

静态方法,使用对象名调用

String

getName() //返回该线程的名称。名称从Thread-0开始 ,

void

setName(String name) 
      改变线程名称,使之与参数 name 相同。

static void

sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行).注意:该方法有异常需要手动处理.

void

start() 导致该线程开始执行;java虚拟机调用这个线程的 run方法。

三、线程安全问题

如果多个线程访问共享数据,则会出现安全问题(售票案例)

同步机制解决安全问题

1、同步代码块
   格式:  synchronized(锁对象){  //深口 奶子的

            //存放可能会出现线程安全问题的代码(访问了共享数据的代码)

    }

  注意:①锁对象可以是任意类的对象.

             ②必须保证多个线程使用的锁对象是同一个.

             ③锁对象要在run()方法外部声明.

   缺点:程序需要频繁的判断锁,获取锁,释放锁,程序效率会低.

2、同步方法

①首先创建一个方法

格式: 修饰符 synchronized 返回值类型 方法名(参数列表){

                                //存放可能会出现线程安全问题的代码(访问了共享数据的代码)

        }

 ②然后调用该方法

3、静态同步方法
格式: 修饰符 static synchronized 返回值类型 方法名(参数列表){

                //存放可能会出现线程安全问题的代码(访问了共享数据的代码)

        }

注意事项:锁对象是本类的class属性.

4Lock接口  //拉克

成员方法

 void

lock()         获取锁。

 void

unlock()         释放锁。

ReentrantLock-->Lock的实现类 //瑞en崔的

使用步骤:

①在成员位置创建一个ReentrantLock对象.

②在可能会出现安全问题之前调用Lock类中的lock方法获得锁.
③在可能会出现安全问题之后调用Lock类中的unlock方法释放锁.  

四、等待唤醒

 Object类中方法

void

wait() //维特 //使线程进入Waiting状态,无线等待

 void

notify() //闹忒fai //唤醒在此对象监视器上等待的时间最长的单个线程。

void

wait(long timeout) 
在过了指定毫秒值还没被唤醒,就会指定醒来.继续执行或进入阻塞状态

void

notifyAll() 
          唤醒在此对象监视器上等待的所有线程。

注意事项:

   ①wait()和和notify()必须要在同步代码块中使用.

   ②同步使用的锁对象要唯一.

   ③只有锁对象才能调用wait()和notify()方法

等待唤醒例子:

public class ClassMain {

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


        Object object = new Object();

        new Thread() {

            @Override

            public void run() {

                while (true) {

                    synchronized (object) {

                        System.out.println("我要买5个包子");

                        try {

                            object.wait();

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                        System.out.println("开始吃包子");

                    }

                }

            }

        }.start();



        new Thread() {

            @Override

            public void run() {

                while (true) {

                    try {

                        Thread.sleep(5000); //此代码块不能放入同步代码块,切记

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    synchronized (object) {



                        System.out.println("老板做好了包子");

                        object.notify();

                    }

                }

            }

        }.start();

    }

}

知识总结:

①当一个线程执行到Thread类中的sleep()方法,该线程会睡眠,将cpu执行权交给其他线程.

②同步代码块等技术保证了该线程会先执行完该代码块中的内容才将cpu执行权交给其他线程,如果遇到wait()会交出cpu执行权.

③当一个线程执行到Object类中的wait()方法,该线程进入无线睡眠状态,此时cpu执行权交给其他线程,必须等待唤醒才能继续本线程.

④被唤醒或者是自己醒后,要与其他线程争抢cpu,如果抢不到,就进入阻塞状态继续等待下一次抢夺.

五、线程池

概念:一个可以容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程消耗资源.

原理:线程池的底层是一个单列集合,依次取出来使用,使用完毕在添加到末尾.

1、Executors类-->生产线程池的类 //A ke 晒可特日

成员方法:

static ExecutorService

newFixedThreadPool(int nThreads) //费可死特
创建一个可重用新的固定线程数的线程池返回值是一个线程池

2、ExecutorService接口

成员方法:

Future

submit(Runnable task) //开启线程任务
传入Runnable的实现类,开启线程任务.

 void

shutdown() 
  关闭线程池

3线程池使用步骤:             

①调用Executors类中的静态方法newFixedThreadPool创建一个指定线程数目的线程池.

②创建一个实现Runnable接口的实现类,重写run()方法,设置线程任务.

③调用ExecutorService接口中的submit()方法,传入Runnable的实现类,开启线程任务.

④调用ExecutorService接口中的shutdowm()方法,关闭线程池.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/592336.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号