首页 > 编程语言 > 详细

线程类、线程池

时间:2019-06-21 23:13:33      阅读:156      评论:0      收藏:0      [点我收藏+]

线程类 Thread

两个构造方法 空参和有参

空参Thread():分配一个新的thread对象,不可指定名字

有参 Thread(String name):创建一个新线程,可起名

常用方法:

start():开启线程

run():执行 描述任务

sleep(long millis):设置毫秒值 让正在执行的线程休眠

创建线程步骤

1.先继承thread类  2.重写run 3.创建子类对象(线程对象)4.调用start方法,开启线程让线程执行,让jvm调用run方法

线程对象调run和调start区别

线程调用run开启线程。调Start 开启线程,让jvm调用run在开启线程中执行

why?继承Thread类原理

Thread类是个默认类,用来描述,我们定义的这个线程做Thread的子类,是为了利用其Thread本有的功能,子继承父,并拥有它的功能

创建线程目的:

目的有单独路径,让多部分代码同时执行

原理图

技术分享图片

看似两个方法同时在运行,其实是CPU快速的切换所以两边都在执行

package com.oracle.demo01;
新建子类
public class MyThread extends Thread{
//    重写run方法
    public void run() {
        for(int i=0;i<20;i++){
            System.out.println("myThread-"+i);
        }
        super.run();
    }
}
package com.oracle.demo01;
测试
public class Demo01 {
    public static void main(String[] args) {        
//        创建新线程(创建子类对象)
        MyThread thread=new MyThread();
//        开启线程 调start()
        thread.start();
        for(int i=0;i<20;i++){
            System.out.println("main-"+i);
        }
    }
}

创建线程方式(继承Thread类)

获取线程名称 

技术分享图片

currentThread()用谁调用就会返回调用当前方法线程的对象

getName()以前获取方法名是用报错的方法获取名称,现在可以直接用getName来代表

在新线程里获得名称,直接用getName就可以,因为里面没有静态

在main里想获得主线程,先获得主线程的对象,在获得主线程名称

package com.oracle.demo01;
//定义一个类继承Thread
public class MyThread extends Thread{
//    重写run方法
    public void run() {
//        getName()获取当前线程名称
        System.out.println("线程名称为"+getName());
        for(int i=0;i<20;i++){
            System.out.println("myThread-"+i);
        }
        super.run();
    }
}
package com.oracle.demo01;
//用.currentThread()获取名称
public class Demo01 { public static void main(String[] args) { // 获取执行当前代码线程的线程对象 Thread th=Thread.currentThread(); // 获取该线程的名称 System.out.println(th.getName()); // 创建新线程(创建子类对象) MyThread thread=new MyThread(); // 开启线程 调start() thread.start(); for(int i=0;i<20;i++){ System.out.println("main-"+i); } } }

创建线程方式-实现Runnable接口(推荐)

接口中的方法 run():

技术分享图片

Thread类构造方法

技术分享图片

步骤:

1.定义类实现Runnable接口

2. 覆盖接口的run方法

3.创建Thread类对象

4 .强Runnable接口子类对象作为参数传递给Thread类的构造函数

5.调用Thread类的start()开启线程

 

package com.oracle.demo01;
//定义一个类 实现Runnable
//让它实现Runnable 让MyRunnable作为新线程任务
public class MyRunnable implements Runnable{
    
    public void run() {
        for(int i=0;i<20;i++){
            System.out.println("Thread-0"+i);
        }
    }
} 
package com.oracle.demo01;
//测试Runnable类接口
public class Demo02 {
    public static void main(String[] args) {
//        创建线程任务对象 :MyRunnable:描述任务
        MyRunnable mr=new MyRunnable();
//        创建Thread类对象:开启线程
        Thread th=new Thread(mr);
//        开启线程
        th.start();
        for(int i=0;i<20;i++){
            System.out.println("main-"+i);
        }
    }
}

实现Runnable原理为什么用Runnable

RunnableThread的接口,“推荐用接口的方式”生成线程,因为接口可以实现多继承 避免单一继承局限性,如果用Thread类,只能继承和创建Thread,如果用Runnable可以实现后可再继承,比Thread多了个备用功能 覆盖Runnable接口的run方法,将线程任务定义到run方法中。将线程的任务从线程的子类中分离出来,进行了单独的封装,按照面向对象思想将任务封装成对象

 线程匿名内部类

 匿名内部类最后得到的是子类或实现对象

package com.oracle.demo01;
//两个匿名内部类方式
public class Neibulei {
    public static void main(String[] args) {
        /*new 父类或接口名(){
            需要重写方法
        }*/
//        1.创建线程方式 继承Thread类
        new Thread(){            
//            重写run(): 写出run然后alt+/
            public void run() { 
                System.out.println(getName()+"这是新线程任务");
            }
//            匿名内部类方式:创建和开启线程一步到位
        }.start();
//        2.实现Runnable接口
        Runnable run=new Runnable(){
            public void run() {
//                获取当前执行线程对象
                String name=Thread.currentThread().getName();
                System.out.println(name+"这是匿名内部类第二个方式");
            }    
//        最后得到的是线程任务对象
        };
        new Thread(run).start();
    }
}

pm

线程池

概念:一个容纳多个线程的容器,可以反复使用,省去创先线程的操作,不用反复创建,消耗资源

线程状态图

技术分享图片

Runnable接口:都是通过线程池工厂创建,再调用线程池中的方法获取线程,再通过线程去执行任务方法

public class MyRun implements Runnable{

    public void run() {
//      获取执行当前线程对象的名字
        String name=Thread.currentThread().getName();
        for(int i=0;i<20;i++){
            System.out.println(name+i);
//          不能throws
            try {
                Thread.sleep(1000);//休眠毫秒值
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

线程池原理图:

技术分享图片

public class Demo01 {
    public static void main(String[] args) {
//      创建线程任务对象
        MyRun mr= new MyRun();
//      创建新线程对象
        Thread th =new Thread(mr);
//      开启线程
        th.start();
    }
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo02 {
    public static void main(String[] args) {
//      用线程池的方式完成线程任务
//      1.从线程池工厂中获取一个装有两条线程的线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
//      2.创建线程任务
        MyRun mr=new MyRun();
//      3.让线程池自主选一条线程执行线程任务(第二个会等第一个的有空了就执行)
        es.submit(mr);
        es.submit(mr);
        es.submit(mr);
        /*//关闭线程池(一般不关闭)
        es.shutdown();*/
    }
}

Callable接口:有泛型,与返回值类型相同

import java.util.concurrent.Callable;

public class MyCallable implements Callable<String>{
    public String call() throws Exception {
        return "abc";
    }
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo01 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
//      1.从线程池工厂中获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
//      2.创建线程任务对象
        MyCallable mc=new MyCallable();
//      3.让线程池自主选择一条线程执行线程任务
        Future<String>    f=es.submit(mc);
//      4.获取线程任务的返回值
        System.out.println(f.get());
    }
}

 Future接口:记录线程任务执行完毕后产生的结果  线程池创建与使用

 get() 获取Future对象中封装的数据结果

import java.util.concurrent.Callable;

public class MyCall implements Callable<Integer>{
    private int num;
    private int num1;
    public MyCall(){}
    public MyCall(int num,int num1){
        this.num=num;
        this.num1=num1;
    }
    public Integer call() throws Exception {
//       计算求和
        int sum=0;
        for(int i=num;i<=num1;i++){
            sum+=i;
        }
        return sum;
    }
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Demo01 {
    //用线程池计算50到100的和------44.....200的和
    public static void main(String[] args) throws InterruptedException, ExecutionException {
//      1.从线程池工厂获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
//      2.创建线程任务对象
        MyCall mc1=new MyCall(50,100);
        MyCall mc2=new MyCall(44,200);
//      3.让线程池自主选择线程执行任务
        Future<Integer> f1=es.submit(mc1);
        Future<Integer>    f2=es.submit(mc2);
//      4.获取线程任务返回值
        int sum1=f1.get();
        int sum2=f2.get();
        System.out.println(sum1);
        System.out.println(sum2);
    }
}

 

线程类、线程池

原文:https://www.cnblogs.com/zs0322/p/11066960.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!