zoukankan      html  css  js  c++  java
  • 线程方法

    使用多线程原因:
    1、当执行某个耗时任务时,需要开启多线程
    2、希望多个任务“同时”执行
    3、防止线程阻塞
    4、完成某个特定的任务
     
     
    进程:正在执行的程序

    线程:具有完成特定任务的一条执行路径,是CPU执行的最小单位(数据传输的基本单位是字节)

    注意:CPU在某个时间刻度上只能够执行一条原子性语句(字节最小是bit位)

    原子性语句:不可再分割的语句
     
    CPU执行原理
    1、真实环境下,除了多核处理器,本质都是CPU在某一个时间点上执行了一条线程
    2、CPU看起来像是同时执行,但是本质上只执行了一条线程的一条原子性语句
    3、在Java的线程程序中,采用的是抢占式调度模式
    4、并发和并行的区别:
     并发:在同一个时间段同时执行
     并行:在同一个时间刻度上同时执行,物理上同时执行
    5、同步和异步的区别:
     同步:本质就是串行执行,并发情况下会出现同步问题
     异步:能够在处理一个任务的同时还能够处理其他事情
    多进程的好处:提高了进程的使用率,从而间接提高了CPU的使用率
    多线程的好处:提高了CPU的使用率
     
    一个Java进程至少包含了2个线程:主线程、垃圾回收线程。

    ----------------------------------------------------------------------------------
    开启线程方式一:
    继承Thread类
    自定义类MyThread继承Thread类。
    MyThread类里面重写run( )方法。
    创建线程对象
    启动线程
    注意:
    1、启动线程使用的是start( )方法,而不是run()方法
    2、线程不能多次启动,否则会报异常
    显示线程的名称:
    Thread.currentThread( )表示当前正在执行的是哪一条线程那么就是对应的那个线程的名称
    Thread.currentThread( ).getName( ) 获取当前正在执行的线程的名称
    run( )线程的核心任务代码区,类似于main方法
    继承Thread的优点:能够直接在子线程访问Thread类的方式(优先访问继承Thread类)
    -----------------------------------------------------------------------------------
    开启线程的方式二(开发中建议使用):
    1、自定义类MyRunnable实现Runnable接口
    2、重写run()方法
    3、创建MyRunnable类的对象
    4、创建Thread类的对象,并把步骤3创建的对象作为构造参数传递
    5、启动线程
    Runnable方式开启线程的好处:
    1、可以避免Java单继承带来的局限性
    2、适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码、数据有效分离,较好的体现了面向对象的设计思想
    --------------------------------------------------------------------------------------------
    开启线程方式三:实现Callable方式开启线程(本质还是方式二,需要依赖一个类FutureTask )
    public class FutureTask<V> implements RunnableFuture<V>  { }
    public interface RunnableFuture<V> extends Runnable, Future<V> { void run( ); }
    public interface Callable<V> {  V call() throws Exception; }
    方式三开启线程的优点:
    1、call方法有返回值,run方法没有返回值,可以返回结果给主线程
    2、call方法可以抛出异常告知主线程(线程通信)
    缺点:会导致主线程在计算完成之前阻塞
    ------------------------------------------------------------------------------------------------
    开启线程方式四:本质是一个继承或者实现了某个类或者接口的子类匿名对象(在Android使用频繁)
    注意:如果同时使用两种方式开启线程,继承Thread方式优先!!!
    匿名内部类开启线程的好处:线程任务执行完毕就是垃圾对象,等待垃圾回收器空闲的时候回收,节约内存资源
    ----------------------------------------------------------------------------------------------------
    Lambda表达方式开启线程
    new Thread( ()->{
         for (int i = 0; i < 100; i++) {
     System.out.println(Thread.currentThread().getName() + ":" + i);
          }
    } ).start();
    函数式接口:只有一个抽象方法的接口称为函数式接口(Runnable)
    ------------------------------------------------------------------------------------------------------
    设置和获取线程的名称
    通过构造方法
    Thread(String name) 分配新的 Thread 对象。
    Thread(Runnable target, String name) 分配新的 Thread 对象。
    通过线程的成员方法
    public final String getName( )
    public final void setName(String name)
    通过静态方法
    public static Thread currentThread( ) 可以获取任意方法所在的线程名称
    可以获取主线程的线程名称:Thread.currentThread( ).getName( ) ;
    获取线程的id: long getId( )
     
    设置和获取线程的优先级
    public final int getPriority( )
    public final void setPriority(int newPriority)
    优先级1~5~10
     
    线程休眠:Thread.sleep(1000L) 阻塞当前正在执行的线程1s
     
    线程中断:public final void stop()终止子线程的生命周期(已停用)

     public void interrupt()给子线程抛出一个异常,子线程还可以继续执行
     
    后台线程:在程序运行的时候在后台提供的一种通用的服务的线程,并且这种线程并不属于程序中不可或缺的部分。
     只要有任何非后台线程还在运行,程序就不会结束。
     
    线程加入:public final void join( )(t.join();//主要用于等待t线程运行结束)
    线程礼让:public static void yield( )让出CPU执行权一小会,一小会不确定多久
     让出了CPU的执行权,释放了执行权,但还可以争夺。
    ===================================================================
    同步线程
    线程安全问题:在多线程环境下,存在多条线程使用多条原子性语句对共享数据做了写操作
    解决办法:1、同步代码块   2、同步方法   3、Lock锁
    同步代码块
    格式:
     synchronized(对象){需要同步的代码;}
    同步的好处:
     解决了多线程的安全问题
    同步的弊端:
     当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,
     降低了程序的运行效率。如果出现了同步嵌套,就容易产生死锁问题

    锁对象:
     锁对象必须是多个线程同一把锁
     锁对象可以是任意对象
     
    同步方法:
    格式:
     public synchronized 返回值 方法名(参数列表){需要同步的代码块}

    如果锁对象是this,就可以考虑使用同步方法。
    方法分为两种:静态方法和非静态方法
    非静态方法的锁对象:this
    静态方法的锁对象:类的字节码文件对象
    注意:synchronized可以修饰方法,修饰代码块,但是不能修饰构造方法、成员变量等。
     
    Lock锁出现死锁现象
    死锁指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象。
    锁对象是任意对象,如果设计在Thread里面,那就定死了,所以和锁有关的方法设计在Object类中
    线程池的作用:能提高线程的效率,一般创建线程消耗时间较长,防止频繁创建而浪费时间

           线程池里的每一个线程代码结束后并不会死亡,而是再次回到线程池中称为空闲状态,等待下一个对象来调用。
    线程池的开启

    Executors工厂类来生产线程池
    调用构造方法:public static ExecutorService newCachedThreadPool()
            public static ExecutorService newFixedThreadPool(int nThreads)
            public static ExecutorService newSingleThreadExecutor( ) 
    -------------------------------------------------------------------------------------------------------------
    线程的开启方式七:定时器
    特点:可以在指定的时间执行指定的任务,同时还可以延时执行或者反复执行
    定时器类:Timer
    定时任务类:TimerTask
    void schedule(TimerTask task, Date time)在指定的时间执行某个任务
    void schedule(TimerTask task, Date firstTime, long period)在指定的时间执行指定的任务
    void schedule(TimeTask task, long delay)延时多长时间执行指定的任务
    void schedule(TimeTask task, long delay, long period)延迟多长时间执行指定的任务到多长周期
     
  • 相关阅读:
    WCF 无法生成 client
    Powershell profile.ps1 cannot be loaded because its operation is blocked by software restriction policies
    信步拾遗之Windwos Live Writer插件
    Maven setting.xml文件详解(转)
    Maven pom.xml详解(转)
    信步漫谈之Maven—基础介绍
    信步漫谈之Nginx—负载均衡
    信步漫谈之Hibernate—基础介绍
    信步漫谈之Dom4j—基础介绍
    信步拾遗之CHM开源文档制作
  • 原文地址:https://www.cnblogs.com/wdss/p/10758880.html
Copyright © 2011-2022 走看看