zoukankan      html  css  js  c++  java
  • Java 多线程一、创建线程的4中方式、线程常用方法

    一、 创建线程的四种方式

    方式一:继承自Thread 类

    方法步骤

    • 1.创建一个继承于Thread类的子类
    • 2.重写Thread 类的 run()方法-> 将线程的执行操作声明到run()中
    • 3.创建Thread 类的子类对象
    • 4.通过此对象调用start() 方法

    例如: 输出0~100 以内所有的偶数

    public class ThreadInheritTest {
        public static void main(String[] args) {
            //3.new 一个继承自Thread类的对象
            MyInheritThread myThread = new MyInheritThread();
    
            //4.启动线程
            myThread.start();
        }
    }
    
    //1.创建一个继承自Thread 的子类
    class MyInheritThread extends Thread {
        //2.重写父类中Thread 的run方法
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    

    注意:我们不能通过run方法启动线程,而是应该通过start方法启动线程。

    方式二:实现Runnable 接口

    方法步骤

    • 1.创建一个实现Runnable接口的类。
    • 2.重写Runnable 类的 run()方法-> 将线程的执行操作声明到run()中
    • 3.创建实现当前Runnable 接口类的对象。
    • 4.将上述对象作为参数传入到Thread 类的构造器中。
    • 5.通过Thread类的对象调用start() 方法启动线程。

    例如:输出1~100 以内所有的偶数

    public class ThreadRunnableTest {
        public static void main(String[] args) {
            MyRunnableThread myRunnableThread = new MyRunnableThread();
            Thread t1 = new Thread(myRunnableThread);
            t1.start();
        }
    }
    
    
    class MyRunnableThread implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    

    方式三:实现Callable 接口

    实现Callable 接口,该接口是JDK 5.0 中新增的。

    步骤

    • 1.创建一个实现Callable 的实现类
    • 2.实现call()方法,将此线程需要执行的操作声明到call()方法中,注意该方法是有返回值的。
    • 3.创建Callable接口实现类的对象
    • 4.将此Callable实现类的对象(numThread)传递FutureTask构造其中,创建FutureTask对象。
    • 5.将FutureTask创建的对象,传递到Thread构造器中,在start该线程。
    • 6.如果关心线程中call()方法的返回值,则可以用个futureTask.get() 来抓取返回值。

    例如:如下代码用于计算0~100以内,所有偶数的和

    package com.jerry.thread10;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.FutureTask;
    
    public class ThreadCallableTest {
        public static void main(String[] args) {
            //3.创建Callable接口实现类的对象
            NumThread numThread = new NumThread();
    
            //4.将此Callable实现类的对象(numThread)传递FutureTask构造其中,创建FutureTask对象。
            FutureTask<Integer> futureTask = new FutureTask<Integer>(numThread);
    
            //5.将FutureTask创建的对象,传递到Thread构造器中,在start该线程。
            new Thread(futureTask).start();
    
            //6.如果关心线程中call方法的返回值,则可以用个futureTask.get() 来抓取返回值。
            try {
                //拿到其返回值
                Integer sum = futureTask.get();
                System.out.println("总和为: " + sum);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    
    //1.创建一个实现Callable 的实现类
    class NumThread implements Callable<Integer> {
    
        //2.实现call方法,将此线程需要执行的操作声明到call方法中,注意该方法是有返回值的。
        @Override
        public Integer call() throws Exception {
            int sum = 0;
    
            for (int i = 0; i <= 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(i);
                    sum += i;
                }
            }
    
            return sum;
        }
    }
    

    注意: 如何理解Callable 接口更强大?

    1. call() 方法是有返回值得。
    2. call() 可以抛出异常,被外面的操作捕获,获取异常信息。
    3. Callable 中是支持泛型的,这个泛型就是用futureTask.get()的返回值。

    方式四:使用线程池(ThreadPool)

    1、使用线程池的好处

    • 1.提高了响应速度(减少了创建线程的时间)
    • 2.降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
    • 3.便于管理,如可设置如下属性管理线程池
        1. corePoolSize 线程池大小
        1. maximumPoolSize 最大线程数
        1. keepAliveTime 线程没有任务时,最多保持多长时间后会终止

    2、步骤

    这里我们只演示了通过Runnable 实现接口方式构建run方法

    • 1.创建一个固定大小的线程池
    • 2.设置线程池属性
    • 3.使用execute执行当前线程,excute适合用于Runnable方式,当线程方法是Callable时要用submit
    • 4.使用shutdown方法关闭当前线程,线程池不用了,则关闭当前线程。

    例如:如下代码创建了固定可容纳10个线程的线程池,当中有两个线程,分别输出奇数和偶数

    package com.jerry.thread10;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadPoolExecutor;
    
    public class ThreadPoolTest {
    
        public static void main(String[] args) {
            //1.创建一个固定大小的线程池
            ExecutorService service = Executors.newFixedThreadPool(10);
            //2.设置线程池属性
            ThreadPoolExecutor executor1 = (ThreadPoolExecutor) service;
            executor1.setCorePoolSize(10);
    
            //3.执行当前线程,适合用于Runnable,Callable 要用submit
            service.execute(new NumThread1());//执行线程1,用于输出偶数
            service.execute(new NumThread2());//执行线程2,用于输出奇数
            //4.关闭当前线程,线程池不用了,则关闭当前线程
            service.shutdown();
        }
    }
    
    class NumThread1 implements Runnable {
        //输出偶数
        @Override
        public void run() {
            for (int i = 0; i <= 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    
    class NumThread2 implements Runnable {
        //输出奇数
        @Override
        public void run() {
            for (int i = 0; i <= 100; i++) {
                if (i % 2 != 0) {
                    System.out.println(Thread.currentThread().getName() + ": " + i);
                }
            }
        }
    }
    

    二、 线程的中的常用方法

    线程中的常用方法如下

      1. start();启动当前线程,调用当前线程中的run() 方法
      1. run(); 通常需要重写Thread 类中的此方法,将创建的线程要执行的操作声明再此方法中
      1. currentThread();静态方法,返回执行当前代码的线程
      1. getName();获取当前线程的名字,也可以根据构造器传参方式命名
      1. setName();设置当前线程的名字
      1. yield(); 释放CPU 的执行权
      1. join(); 当前线程先暂停,切换到另一个线程,等另一个线程执行完,才能执行当前线程
      1. stop(); 已过时。用于强制结束当前线程
      1. sleep(long millitime);线程挂起多少毫秒

    三、 线程的优先级

    说明:线程是分优先级的,线程的优先级由1~10,分为10个等级,数字越大,优先级越高。
    可以看到优先级在Thread类中定义了一个枚举,具体如下:

    • MIN_PRIORITY = 1;
    • NORM_PRIORITY = 5;
    • MAX_PRIORITY = 10;

    如何设置优先级?

    • 可以通过thread.setPriority(1~10) 来设置优先级的高低,其中thread 对象为继承自Thread实现的对象。

    如下代码演示如何去设置线程的优先级

    public class ThreadTest {
        public static void main(String[] args) {
            ThreadPriority thread = new ThreadPriority("Sub Thread: 1");
    		//设置优先级为最大10
            thread.setPriority(Thread.MAX_PRIORITY);
            thread.start();
    
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName() + " : " + i);
            }
        }
    }
    
    class ThreadPriority extends Thread {
        ThreadPriority(String name) {
            super(name);
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                if (i % 2 == 0) {
                    System.out.println(Thread.currentThread().getName() + " : " + i);
                }
            }
        }
    }
    

    注意:
    设置了高优先级的线程,只是优先去执行它,并不是说他必须全部执行完,才会切换到低优先级的线程。
    从概率上来讲,CPU 优先执行高优先级的线程

  • 相关阅读:
    JQuery DOM操作
    JQuery 选择器和事件
    LinQ 组合查分页
    LinQ
    web 图片验证码 验证
    Web 上传图片加水印
    Web 组合查询加 分页
    ajax连接数据库加载+三级联动
    jq动画
    jq基础
  • 原文地址:https://www.cnblogs.com/vpersie2008/p/12801097.html
Copyright © 2011-2022 走看看