学习线程之前需要了解程序、进程、线程的区别

程序

程序是一组为完成一些特殊功能的计算机指令的集合。

进程

进程是正在运行中的程序,是系统进行资源分配和调用的独立单位,每个继承都有它自己的内存空间和系统资源。

线程

在一个进程中的内部可以执行多个任务,而这每一个任务可以看作一个线程。线程是程序中控制流,是程序使用CPU的基本单位

多线程的意义

多线程的作用不是提高执行速度,而是提高应用程序、CPU的使用率

在Java中多线程的使用
创建一个线程类的两种方式

很多人说Java创建线程有三种方式,当根据jdk1.8API来看,只有两种。可能是官方只认两种,也有可能是还没更新官方文档,以下写出三种方式:

  1. 继承Tread类并重写run()方法
public class ThreadTest01 extends Thread{
//    public ThreadTest01(String name) {
//        super(name);
//    }

    @Override
    public void run() {
        // 一般被线程执行的代码一定比较耗时
        for (int i = 0; i < 10; i++) {
            String name = super.getName();
            System.out.println(name + i);
        }
    }
}


package com.MultiThreading;

/**
 * start()和run()的区别
 * start()方法首先启动线程,然后由jvm区调用该线程的run方法
 * run()仅仅是封装线程执行的代码,直接调用相当于普通方法
 */
public class Test01 {
    public static void main(String[] args) {

        // 创建线程对象
        ThreadTest01 test01 = new ThreadTest01();
        ThreadTest01 test02 = new ThreadTest01();
    
        // 直接调用run方法,相当于调用普通方法,所以看到的是单线程的效果
//        test01.run();
//        test01.run();


        // IllegalThreadStateException:非法线程状态异常,相当于一个线程启动两次
//        test01.start();
//        test01.start();

        // 启动线程
        test01.start();
        test01.setName("线程一");
        test02.start();
        test02.setName("线程二");

        // 返回当前正在执行线程对象
        Thread.currentThread().setName("主线程");
        System.out.println(Thread.currentThread().getName());
    }
}



/**
 * start()和run()的区别
 * start()方法首先启动线程,然后由jvm区调用该线程的run方法
 * run()仅仅是封装线程执行的代码,直接调用相当于普通方法
 */
public class Test01 {
    public static void main(String[] args) {

        // 创建线程对象
        ThreadTest01 test01 = new ThreadTest01();
        ThreadTest01 test02 = new ThreadTest01();
    
        // 直接调用run方法,相当于调用普通方法,所以看到的是单线程的效果
//        test01.run();
//        test01.run();


        // IllegalThreadStateException:非法线程状态异常,相当于一个线程启动两次
//        test01.start();
//        test01.start();

        // 启动线程
        test01.start();
        test01.setName("线程一");
        test02.start();
        test02.setName("线程二");

        // 返回当前正在执行线程对象
        Thread.currentThread().setName("主线程");
        System.out.println(Thread.currentThread().getName());
    }
}
  1. 实现Runnable接口并实现run()方法
public class RunnableTest03 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName() + "\t" + i);
        }
    }
}


public class Test03 {
    public static void main(String[] args) {
        RunnableTest03 runnableTest03 = new RunnableTest03();
        Thread thread = new Thread(runnableTest03);
        thread.start();
    }
}
  1. 实现Callable接口并实现call()方法
import java.util.concurrent.Callable;

public class CallableDemo implements Callable<Object> {
    @Override
    public Object call() throws Exception {
        int i = 1111;
        return i;
    }
}

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

public class CallableTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableDemo callableDemo = new CallableDemo();
        FutureTask futureTask = new FutureTask(callableDemo);
        Thread thread = new Thread(futureTask);
        thread.start();
        Object o = futureTask.get();
        System.out.println(o);
    }
}

上述三种方式都可以创建一个线程类用来达到多线程的目的。

多线程常用方法
  1. 线程对象名.start():启动线程
  2. 线程对象名.setName():设置线程名
  3. 线程对象名.getName():获取线程名
  4. Tread.currentThread():返回当前正在执行的线程对象
  5. 线程对象名.setPriority(int newPriority):设置线程优先级;默认优先级为5,最高优先级为10,最低优先级为1。注意,优先级高不代表一定会让它最先获得CPU资源,只能说它最先获取CPU资源的概率相较于优先级低的线程会大一点。设置优先级要在启动线程前设置,否则无效。
  6. 线程休眠Thread.sleep(millis):单位为毫秒值(1s = 1000ms),设置线程睡眠时间。eg:Thread.sleep(1000)
  7. 线程加入:等待线程终止,才继续执行下一个线程(在启动线程之后调用)线程对象名.join()
  8. 线程让步\线程礼让:暂停当前正在执行的线程对象(即放弃当前拥有的CPU资源),并执行其他线程。并不能保证一个线程执行一次,Thread.yield(),在线程体中执行
  9. setDaemon(boolean on):将指定线程标记为守护线程或用户线程。当程序中运行的线程都为守护线程时,Java虚拟机退出。
    10.中断线程:
    stop():让线程停止(已过时)
    interrupt():中断线程,把线程的状态转为终止状态,并抛出InterruptedException
线程组

把多个线程组合到一起,可以对多个线程分类管理,Java允许程序直接对线程控制
默认属于main线程组
更改默认线程组
- 创建一个线程组
- 创建其他线程时,把其他线程的组指定为创建的线程组

ThreadGroup tg = new ThreadGroup();
Thread t = new Thread(tg, new RunnableImpl());