多线程一

1 程序、进程和线程的概念

1.1 程序

  • 是为完成特定任务,用某种语言编写的一组指令的集合。即指一段静态的代码。

1.2 进程

  • 是程序的一次执行过程或者是正在运行的一个程序。
  • 是一个动态的过程:有它自身的产生、存在和消亡的过程。-----生命周期。
  • 如:运行中的QQ、运行中的MP3播放器。
  • 程序是静态的,进程是动态的。
  • 进程作为资源分配的单位,系统在运行的时候会为每个进程分配不同的内存区域。

1.3 线程(Thread)

  • 进程可以进一步细化为线程,是一个程序内部的一条执行路径。
  • 如果一个进程同一时间并行执行多个线程,就是支持多线程的。
  • 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器,线程切换的开销小。
  • 一个进程中的多个线程共享相同的内存单位/内存地址空间(它们从同一堆中分配对象,可以访问相同的变量和对象)。这就使得线程间的通信更简便、高效。但多个线程操作共享的系统资源可能会带来安全的隐患。

多线程一_第1张图片

 

2 单核CPU和多核CPU的理解

  • 单核CPU,其实是一种假的多线程,因为在一个时间段内,只能执行一个人线程的任务。例如:虽然有多车道,但是收费站只有一个工作人员在收费,只有收费了才能通过,那么CPU就好比收费人员。如果某个人不想交钱,那么收费人员可以把他“挂起”(晾着他,等他想通了,准备好了钱,再去收费)。但是因为CPU执行速率太快,以至于我们感觉不到。
  • 如果是多核CPU的话,更能发挥多线程的效率。当然,现在的服务器都是多核的。
  • 一个Java应用程序,其实至少有三个线程:main()方法主线程,gc垃圾回收线程,异常处理线程。如果不处理异常的情况下,发生异常会影响到主线程。

 

3 并发和并行

3.1 并行

  • 多个CPU同时执行多个任务。比如:多个人同时做不同的事。

3.2 并发

  • 一个CPU(采用时间片轮转算法)同时执行多个任务。比如:秒杀、多个人做同一件事。

 

4 使用多线程的优点

  • 背景:以单核CPU为例,只使用单个线程先后完成多个任务肯定比用多个线程来完成的时间更短,为什么还要用多线程尼?

 

  • 多线程的优点:
  • ①提高了应用程序的响应。对图形化界面更有意义,增加了用户的体验。
  • ②提高计算机系统CPU的利用率。
  • ③改善程序结构。将既长又复杂的进程分为多个线程,独立运行,利于理解和修改。

 

5 什么时候需要多线程

  • 程序需要同时执行两个或多个任务。
  • 程序需要实现一些需要等待的任务,如用户输入、文件读写操作、网络操作、搜索等。
  • 需要一些后台运行的程序时。

 

6 创建线程的方式一

6.1 步骤

  • 定义子类继承Thread类。
  • 子类去重写Thread类中的run()方法。
  • 创建Thread子类对象,即创建了线程对象。
  • 调用线程对象的start()方法:启动线程,调用run()方法。

6.2 创建线程的方式一的应用示例

  • 示例:
package day18;

public class EvenThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + "偶数是:" + i);
            }
        }
    }
}
package day18;

public class ThreadTest {
    public static void main(String[] args) {
        EvenThread thread1 = new EvenThread();

        //start()方法  ①启动当前线程 ②调用当前线程中的run()方法
        thread1.start();

        //如下的操作是在主线程(main()方法)中执行的
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println("主线程执行结束:" + i);
            }
        }
    }
}

 

  • 示例: 创建2个线程,其中一个线程遍历100以内的偶数,另一个线程遍历100以内的奇数。
package day18;

public class EvenThread extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 == 0) {
                System.out.println(Thread.currentThread().getName() + "偶数是:" + i);
            }
        }
    }
}
package day18;

public class OddThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if (i % 2 != 0) {
                System.out.println(Thread.currentThread().getName() + "奇数是:" + i);
            }
        }
    }
}
package day18;

public class ThreadTest {
    public static void main(String[] args) {
        EvenThread evenThread = new EvenThread();

        OddThread oddThread = new OddThread();

        evenThread.start();
        oddThread.start();
    }
}

 

7 线程的常用方法

  • 启动线程,并执行对象的run()方法。
public synchronized void start();
  • 线程被调用时执行的操作。
public void run();
  • 返回线程的名称。
public final String getName();
  • 设置线程的名称。
public final synchronized void setName(String name);
  • 返回当前的线程。在Thread子类中就是this,通常用于主线程和Runnable实现类。
public static native Thread currentThread();
  • 线程让步。暂停当前执行的线程,把执行机会让给优先级相同或更高的线程。
public static native void yield();
  • join():当某个程序执行中调用其他线程的join()方法的时候,调用线程将被阻塞,知道join()方法加入的join线程执行完毕为止。
public final void join() throws InterruptedException();
  • 线程睡眠:让当前活动的线程在指定的时间段内放弃对CPU的执行权,使得其他线程有机会被执行,时间到了重新排队。
 public static native void sleep(long millis) throws InterruptedException;

 

8 创建线程的方式二

8.1 步骤

  • 定义子类,实现Runnable接口。
  • 子类中重写Runnable接口中的run()方法。
  • 通过Thread类的有参构造器创建线程对象。
  • 将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。
  • 调用Thread类的start方法,开启线程。

8.2 创建线程的方式二的应用示例

  • 示例:
package day18;

public class TicketThread implements Runnable {
    private int tickets = 100;

    @Override
    public void run() {
        for (;;){
            if (tickets >= 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("票数:" + tickets--);
            }
        }


    }
}
package day18;

public class ThreadTest {
    public static void main(String[] args) {
        TicketThread t = new TicketThread();

        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);

        t1.start();
        t2.start();
    }
}

 

你可能感兴趣的:(多线程一)