JAVA-多线程知识点总结(一)

简介: JAVA-多线程知识点总结(一)

一、相关概念

1.1程序、进程和线程的概念:

程序:是一系列指令的集合,即指的是一段静态的代码,静态对象

进程:是运行的程序,是CPU分配资源的最小单位。

线程:是进程的实体,是CPU调度和分派的基本单位。

1.2进程和线程的主要区别:

1.从属关系不同:进程是正在运行程序的实例,进程中包含了线程,而线程中不能包含进程(即一个进程可以拥有多个线程,而一个线程同时只能被一个进程所有)。


2.描述侧重点不同:进程是操作系统分配资源的基本单位,而线程是操作系统调度的基本单位。


3.共享资源不同:多个进程间不能共享资源,每个进程有自己的堆、栈、虚存空间(页表)、文件描述等信息,而线程可以共享进程资源文件(堆,方法区),并且有自己私有的堆、栈。


4.上下文切换速度不同:线程切换速度较快(指的是从一个线程切换到另一个线程),而进程切换较慢。

5.操纵者不同:一般情况下,进程的操纵者是操作系统,线程的操纵者是编程人员。

1.3引入线程的原因:

1.便于调度。

2.线程可以共享简称的数据和代码,启动和切换速度更快。

3.具有高并发性,可以启动多个线程执行同一个程序的进程。

4.充分利用处理器的功能。

并发:指两个或两个以上的事件在同一时间隔发生,微观上,是把事件分成若干段,使多个进程快速交替的执行。

并行:指两个或两个以上的事件在同一时刻发生,无论是微观还是宏观上,二者都是一起执行的。

1.4多进程和多线程:

多进程:每个进程互相独立,不影响主程序的稳定性,通过增加CPU可以扩充软件的性能,可以减少线程加锁/解锁的影响,极大提高性能。缺点是多进程逻辑控制复杂,需要和主程序交互,需要跨进程边界,进程之间上下文切换比线程之间上下文切换代价大。


多线程:无需跨进程,程序逻辑和控制方式简单,所有线程共享该进程的内存和变量等。缺点是每个线程与主程序共用地址空间,线程之间的同步和加锁控制比较麻烦,一个线程的崩溃会影响到整个进程或者程序的稳定性。

二、创建和启动线程。

2.1线程的创建方式
*****继承Thread类

①创建一个继承于Thread类的子类

②重写Thread类的run()【此线程要执行的操作,声明在此方法体中】

③创建当前Thread的子类的对象

④通过对象调用start():启动当前线程,调用当前线程的run()

class MyThread extends Thread{
 
    //重写run方法,run 表示这个线程需要执行的任务
    @Override
    public void run() {
        System.out.println("这个线程需要执行的任务");
    }
}
 
public class ThreadDemo {
    public static void main(String[] args) {
 
           //创建一个 MyThread 实例
            MyThread myThread = new MyThread();
 
           //start 方法表示这个线程开始执行,注意,这里不是调用 run()方法
          myThread.start();
 
            }
         }
*****实现Runnable接口

①创建一个实现Runnable接口的类

②实现接口中的run()【此线程要执行的操作,声明在此方法体中】

③创建当前实现类的对象

④将此对象作为参数传递到Thread类的构造器中,创建Thread类的实例

⑤Thread类的实例调用start():

 
class MyRunnable implements Runnable{
 
    //需要重写run方法
    @Override
    public void run() {
        System.out.println("这个线程需要执行的任务");
    }
}
 
public class ThreadDemo {
    public static void main(String[] args) {
 
         
           //创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为参数。
           Thread thread = new Thread(new MyRunnable());
 
           //start 方法表示这个线程开始执行,注意,这里不是调用 run()方法
          myThread.start();
 
            }
         }

*****实现Callable(jdk5.0增)

实现者定义了一个不带参数的方法,称为call。 Callable接口与Runnable接口类似,两者都是为其实例可能由另一个线程执行的类设计的。


与Runnable方式对比的好处是:


---call()可以有返回值,更加灵活。

---call()可以使用throws的方式处理异常。

---callable使用了泛型参数,可以指明具体的call()返回值类型。

缺点:如果在主线程中需要获取分线程call()的返回值,则此时的主线程是阻塞状态的。

 
 
public class MyCallable implements Callable<Integer> {
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
 
    public static void main(String[] args) throws InterruptedException和 ExecutionException {
        MyCallable myCallable = new MyCallable();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            int result = futureTask.get();
            System.out.println("The result is " + result);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

*****使用线程池

线程池解决两个不同的问题:它们通常在执行大量异步任务时提高性能,因为减少了每个任务的调用开销,并且它们提供了一种方法来限制和管理执行任务集合时消耗的资源(包括线程)。每个ThreadPoolExecutor(阿里推荐)还维护一些基本的统计信息,比如完成任务的数量。


使用线程池的好处:


---提高了程序执行的效率。(线程早已提前创建好了)


---提高了资源的复用率。(执行完的线程并未销毁,而是可以继续执行其他的任务)


---可以设置相关的参数,对线程池中的线程的使用进行管理。

 java.util.concurrent.ThreadPoolExecutor类的构造器(其一):
 
public ThreadPoolExecutor(int corePoolSize,
                         int maximumPoolSize,
             long keepAliveTime,
             TimeUnit unit,
             BlockingQueue<Runnable> workQueue,
             ThreadFactory threadFactory,
                         RejectedExecutionHandler handler) 
     {
      if (corePoolSize < 0 ||
      maximumPoolSize <= 0 ||
      maximumPoolSize < corePoolSize ||
      keepAliveTime < 0)
      throw new IllegalArgumentException();
      if (workQueue == null || threadFactory == null || handler == null)
      throw new NullPointerException();
      this.acc = System.getSecurityManager() == null ?null :
      AccessController.getContext();
      this.corePoolSize = corePoolSize;
      this.maximumPoolSize = maximumPoolSize;
      this.workQueue = workQueue;
      this.keepAliveTime = unit.toNanos(keepAliveTime);
      this.threadFactory = threadFactory;
      this.handler = handler;
}
相关文章
|
22小时前
|
Java
java线程之用户线程与守护线程
java线程之用户线程与守护线程
6 1
java线程之用户线程与守护线程
|
22小时前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
6 1
|
22小时前
|
Java
java线程之定制化通信(多轮顺序打印问题)
java线程之定制化通信(多轮顺序打印问题)
6 1
|
22小时前
|
安全 Java
java线程之线程安全
java线程之线程安全
13 1
|
19小时前
|
缓存 安全 Java
如何使用Java实现高效的多线程编程
如何使用Java实现高效的多线程编程
|
20小时前
|
安全 Java 机器人
Java中的多线程编程实用指南
Java中的多线程编程实用指南
|
21小时前
|
Java
java线程之异步回调
java线程之异步回调
4 0
|
21小时前
|
Java
java线程之读写锁
java线程之读写锁
5 0
|
21小时前
|
Java
java线程之信号同步
java线程之信号同步
7 0