• Java学习--线程(一)


     目录

       1.进程与线程

      2.线程的实现方式

      3.线程的生命周期

    一、进程与线程

      进程:运行的程序和它所需要的资源(CPU、内存)

      线程:线程是进程的一部分,粒度比进程小,一个进程可以拥有多个线程,至少包含一个线程,这个线程就是主线程。

      线程与进程的区别:

      1.一个进程里面至少拥有一个线程

      2.线程之间使用的资源是共享的。

      3.线程之间的通信比进程间的通信开销小

      4.线程的创建相对于进程的创建容易

    ps:1.进程包含线程,可以有多个,至少有一个

      2.线程是独立的,CPU抢占式,也就是当前运行的线程很有可能被暂停(挂起)很小时间片

      3.进程间的内存空间是独立的,但是线程间的内存空间是共享的。

      4.由于共享,线程间运行效率大大提高,利于线程间的通信(数据交换)

      5.线程的创建比进程的创建小的多,使用比较多。

    使用多线程的目的:

      最大效率的使用CPU资源,提高程序的运行效率

      ps:真正的多线程是建立在多核CPU的基础上的。

    二、线程的实现方式

      1.继承Thread   重写run方法

      2.实现Runnable接口  重写run方法

         3.带返回值的线程创建

       Callable 和FutureTask

       返回值获取方法 FutureTask对象的get()方法

      ps:推荐使用第二种   。原因 :Java类的接口可以多实现,而继承只能单继承

      注:run方法中如果有异常时不能抛出去的。   原因:run方法时重写的,而父类或端口中的run方法是没有申明异常的。

    FutureTask的API

     

    三、线程的生命周期

    创建:实例化一个线程对象 new Thread()
    就绪:start方法执行或者阻塞结束后
    运行:获得CPU的时间片,执行run方法
    阻塞:暂停(挂起),IO、sleep、wait、join
    结束:run方法结束或者异常

    线程的名称--主线程默认名称是main,子线程的默认名称则是Thread-0,Thread-1...

    一下是线程的简单实现代码:

    package com.demo.thread;

    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;

    /**
    * 线程的简单实现
    * @author Administrator
    *
    */
    /**
    * 主线程
    * @author Administrator
    *
    */
    public class ThreadExample {
    /**
    * 主线程里面启动子线程
    * @param args
    */
    public static void main(String[] args) {
    //启动用继承实现的线程
    ThreadExample1 threadExample1 = new ThreadExample1();
    threadExample1.setName("线程1");
    threadExample1.start();
    //启动用接口实现的线程
    new Thread(new ThreadExample2(),"线程2").start();
    //启动带返回值的线程
    FutureTask<String> futureTask = new FutureTask<>(new ThreadExample3());
    try {
    new Thread(futureTask,"线程3").start();
    String s = futureTask.get();
    System.out.println(Thread.currentThread().getName()+"--------"+s);
    } catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
    }
    }
    }
    /**
    * 继承Thread的线程
    * @author Administrator
    *
    */
    class ThreadExample1 extends Thread{
    @Override
    public void run() {
    super.run();
    for(int i = 0;i<10;i++){
    System.out.println(Thread.currentThread().getName()+"--------"+i);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    }
    }
    /**
    * 实现runnable接口的线程
    * @author Administrator
    *
    */
    class ThreadExample2 implements Runnable {

    @Override
    public void run() {
    for(int j=0;j<10;j++){
    System.out.println(Thread.currentThread().getName()+"--------"+j);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }

    }
    /**
    * 实现callable接口的带返回值的线程
    * @author Administrator
    *
    */
    class ThreadExample3 implements Callable<String>{

    @Override
    public String call() throws Exception {
    return "带返回值得线程";
    }
    }

    线程的优先级

      1-10 从低到高

      默认的优先级是5,优先级越高,获得CPU的时间片越大 

    sleep方法

      sleep方法能让线程进入阻塞状态,带一个时间参数(毫秒),经过休眠毫秒数后线程进入就绪状态。会有中断异常抛出

      

    yield方法

      yield方法能让线程直接进入就绪状态,会有中断异常抛出。

      

    join方法

      join方法能让线程合并,让多个线程合并到一个线程中进入阻塞状态,程序运行将会进入阻塞状态,会有中断异常抛出。

      

    以下是join方法的具体代码与结果

    package com.demo.thread;
    
    public class JoinDemo {
        public static void main(String[] args) {
    
            JoinThread thread = new JoinThread();
            thread.start();
            System.out.println("over");
        }
        
    }
    class JoinThread extends Thread{
        @Override
        public void run() {
            super.run();
            for(int i =0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"------"+i);
            }
        }
    }
    不加join方法线程

    package com.demo.thread;
    
    public class JoinDemo {
        public static void main(String[] args) throws InterruptedException {
    
            JoinThread t = new JoinThread();
            t.start();
            t.join();
            System.out.println("over");
        }
        
    }
    class JoinThread extends Thread{
        @Override
        public void run() {
            super.run();
            for(int i =0;i<10;i++){
                System.out.println(Thread.currentThread().getName()+"------"+i);
            }
        }
    }
    添加join方法的线程

     

    sleep方法与yield方法的区别

      1)sleep方法带参数,可以指定休眠时长,进入阻塞状态CPU让给其他线程,当休眠时间到了后,进入就绪状态。
      2)yield方法没有参数,CPU时间片让给同优先级或者优先级更高的线程,直接进入到就绪状态。有可能刚调用yield方法,又被CPU选中执行。
      3)sleep方法抛出中断异常,yield方法没有
      4)yied方法不太可控,所以一般不推荐使用来控制线程的并发问题sleep方法的可移植性强。

  • 相关阅读:
    为什么byte取值负128到127.md
    傻傻分不清?Integer、new Integer() 和 int 的面试题
    Spring 面试 7 大问题,你顶得住不?
    消息中间件ActiveMQ、RabbitMQ、RocketMQ、ZeroMQ、Kafka如何选型?
    poj 3684 Physics Experiment(数学,物理)
    poj 3320 Jessica's Reading Problem(尺取法)
    java面试
    nyoj 234 吃土豆
    Web 通信 之 长连接、长轮询(long polling)
    XHTML使用规范
  • 原文地址:https://www.cnblogs.com/bananafish/p/9638802.html
Copyright © 2020-2023  润新知