• 多线程--线程的创建与启动


    创建一个线程,Java提供三种方法

    (1)通过实现Runnable接口,重写run方法

    (2)通过继承Thread类本身,--必须重写

    (3)通过Callable和Future创建线程

    Thread类的方法

    void start()使该线程开始执行,Java虚拟机调用该线程的run方法。

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

    setPriority(int priority)更改线程的优先级

    join(long millisec)等待该线程终止的时间最长为milli毫秒

    interrupt()中断线程

    boolean isAlive()测试线程是否处于活动状态

    上述方法被Thread对象调用

    下面的方法是Thread类的静态方法static

    yield()放弃CPU的使用权力

    sleep(long millisec)休眠线程

    currentThread()获得正在执行的线程对象

    概念解析:

    并行:是真正的同时。

    并发:通过CPU调度算法,用户看上去同时执行,实际上从CPU层面上不是真正同时。

    线程安全:并发情况下,多线程使用,线程调度顺序不影响任何结果。

    同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问称为线程安全的--结果正确。

    Thread和Runnable的区别

    如果一个类继承Thread,则不合适资源共享,但是如果实现了Runnable接口,则很容易实现资源共享。

    线程是CPU的调度单位,进程是操作系统的调度单位。

    Method类中有个方法invoke()

    public Object invoke(Object obj,Object ...args)

    通俗点讲就是:对象调用的方法(对象.参数)


    守护线程(DaemonThread)

    守护线程具有最低的优先级;

    是用来服务用户线程的。

    (1)thread.setDaemon(true)必须在thread.start()之前设置。

    (2)在Daemon线程中产生的新的线程也是Daemon的。

    (3)守护线程不去访问固有的资源,如文件,数据库。

    用户线程(userThread)

    Thread和Runnable创建出来的线程。

    线程的生命周期大体分为5种状态

    1.New:通过new创建了Thread类或其子类对象。

    2.Runnable: a)指Thread类对象调用了start()方法,这时的线程就等待时间片轮转到自己这,以便获得CPU;b)线程在处于Runnable状态时并没有运行完自己的run方法,时间片用完之后回到Runnable状态; c) 处于Blocked状态的线程结束当前的Blocked状态之后重新回到Runnable状态。

    3.Running:线程已获CPU运行。

    4.Dead:处于Running的线程,执行完run方法之后,就变成了Dead状态。

    5.Blocked:处于Running状态的线程出于某种原因,让出当前CPU 给其他线程。


    线程的创建与启动

    继承Thread类:重写run方法

     1 package NiuMuThread;
     2 
     3 public class MyThread extends Thread{
     4 
     5     @Override
     6     public void run() {
     7         // TODO Auto-generated method stub
     8         for(int i=0;i<100;i++) {
     9 //            线程的静态方法-----当前线程----的名字
    10             System.out.println(Thread.currentThread().getName()+":"+i);
    11             try {
    12                 Thread.sleep(100);
    13             } catch (InterruptedException e) {
    14                 // TODO Auto-generated catch block
    15                 e.printStackTrace();
    16             }
    17         }
    18     }
    19 }

    实现Runnable接口:重写run方法

     1 package NiuMuThread;
     2 
     3 public class MyThread2 implements Runnable{
     4 
     5     @Override
     6     public void run() {
     7         // TODO Auto-generated method stub
     8         for(int i=0;i<100;i++) {
     9 //            线程的静态方法-----当前线程----的名字
    10             System.out.println(Thread.currentThread().getName()+":"+i);
    11             try {
    12                 Thread.sleep(100);
    13             } catch (InterruptedException e) {
    14                 // TODO Auto-generated catch block
    15                 e.printStackTrace();
    16             }
    17         }
    18     }
    19 }

    测试:

     1 package NiuMuThread;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6         //第一个线程
     7         MyThread thread=new MyThread();
     8         //第三个线程
     9         MyThread2 r=new MyThread2();
    10         
    11         Thread th2=new Thread(r);
    12         thread.start();//启动线程
    13         th2.start();
    14         
    15         //第二个线程
    16         for(int i=0;i<100;i++) {
    17 //            线程的静态方法-----当前线程----的名字
    18             System.out.println(Thread.currentThread().getName()+":"+i);
    19             try {
    20                 Thread.sleep(100);
    21             } catch (InterruptedException e) {
    22                 // TODO Auto-generated catch block
    23                 e.printStackTrace();
    24             }
    25         }
    26     }
    27 }

    注意:通过实现Runnable接口的,需要 new Thread(runnable),才能创建线程对象

    ***在线程的Thread对象上调用start()方法,而不是run()或者别的方法。

    一些常见的问题

    1.线程的名字,一个运行中的线程总是有名字的,名字有两个来源,一是虚拟机自己给的名字,或者是你自己定的名字。在没指定线程名字的情况下,虚拟机会为线程指定名字,主线程的名字是main,非主线程的名字不确定。

    2.线程都可以设置名字,也可以获取线程的名字。

    3.获取当前线程的对象的方法是:Thread.currentThread();

    4.在上面代码中,只能保证:每个线程都将启动,每个线程都将运行直到完成。一系列线程以某种顺序启动并不意味着将按该顺序执行。对于任何一组启动的线程来说,调度程序不能保证其执行次序,持续时间也无法保证。

    5.当线程目标run()方法结束时线程完成。

    6.一旦线程启动,它就永远不能在重新启动。只有一个新的线程可以被重新启动,并且只能一次。一个可运行的线程或者死线程可以被重新启动。

    7.线程的调度是JVM的一部分,在一个CPU的机器上,实际上一次只能运行一个线程。一次只有一个线程栈运行。JVM线程调度程序决定实际运行哪个处于可运行状态的线程。

    众多可运行线程中的某一个会被选中作为当前线程。可运行线程被选择的顺序是没有保障的。

    8.尽管通常采用队列形式,但这是没有保障的。队列形式是指当一个线程完成“一轮”时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端为止,它才能被再次选中。事实上,我们把它称为可运行池而不是一个可运行队列,目的是帮助认识线程并不都是以某种有保障的顺序排列。

    9.尽管我们没有无法控制线程调度程序,但可以通过别的方式来影响线程的调度方式。

  • 相关阅读:
    ModelForm中手动给某些字段赋值
    Ubuntu 18.04.4 LTS 安装Torch步骤
    High-Resolution Image Inpainting using Multi-Scale Neural Patch Synthesis
    Semantic Image Inpainting with Deep Generative Models
    Context Encoders: Feature Learning by Inpainting
    Focus Manipulation Detection via Photometric Histogram Analysis
    Learning to Detect Fake Face Images in the Wild
    A general approach to detect tampered and generated image
    Image splicing forgery detection combining coarse to refined convolutional neural network and adaptive clustering
    Detecting GAN-generated Imagery using Color Cues
  • 原文地址:https://www.cnblogs.com/xjs1874704478/p/10742672.html
Copyright © 2020-2023  润新知