Java 多线程实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Luomingkui1109/article/details/79957874
1.线程的概念:
    什么是程序(program ):为了完成某项特定的任务,使用某种语言,编写一组指令的集合。即指一段静态的代码,静态对象。
    什么是进程(process ): 程序的一次执行过程,或是正在运行的一个程序。动态过程:有它自身的产生、存在和消亡的过程。
    什么是线程(thread ):在一个进程中,执行的一套功能流程,称为线程。
                                    在一个进程中,执行的多套功能流程,称为多线程。
     抢占式策略系统: 系统会分配给每个执行任务的线程一个很小的时间段用于执行任务,当该时间段用完后, 系统会剥夺其 cpu 使用权,交给其他线程执行。

2.为什么使用多线程?
    为了解决负载均衡问题,充分利用CPU资源.为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰。
    为了处理大量的IO操作时或处理的情况需要花费大量的时间等等,比如:读写文件,视频图像的采集,处理,显示,保存等。

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

4.多线程的缺点:
    如果有大量的线程,会影响性能,因为操作系统需要在它们之间切换.
    更多的线程需要更多的内存空间
    线程中止需要考虑对程序运行的影响.
    通常块模型数据是在多个线程间共享的,需要防止线程死锁情况的发生

5.多线程特点:
    高内聚,低耦合
    线程操作资源类

6.Java 实现多线程的几种方式
方式一:
    ① 声明一个类继承 Thread 类
    ② 重写 run() 方法,同时编写线程执行体
    ③ 创建该子类的实例
    ④ 调用 start() 方法启动线程,默认调用 run() 方法
public class MyThread extends Thread{
     public MyThread(){}
     public void run(){
         for (int i = 0;i<100;i++) {
              System.out.println("子線程"+i);
         }
     }
}
public class TestThread {
     public static void main(String[] args) {
         MyThread mt = new MyThread();
         mt.start();
     }
}
方式二:
    ① 声明一个类实现 Runnable 接口    
    ② 实现 run() 方法,同时编写线程执行体    
    ③ 创建该实现类的实例
    ④ 创建 Thread 类的实例,将实现类的实例作为参数传递给 Thread 的构造器
    ⑤ 调用 Thread 的 start() 方法, 启动线程,默认调用 run() 方法
public class PrimeRun implements Runnable{
     @Override
     public void run() {
         for (int i = 0; i < 100; i++) {
              if(i % 2 == 0){
                   System.out.println(Thread.currentThread().getName() + ":" + i);
              }
         }
     }
}
public class TestThread2 {
     public static void main(String[] args) {
         PrimeRun pr = new PrimeRun();
         Thread t1 = new Thread(pr);
         t1.start();
         Thread t2 = new Thread(pr);
         t2.start();
     }
}
说明:继承 Thread 类 实现 Runnable 接口的区别?    
    ① Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。 
    ② 若需要多个线程访问共享数据时,首选使用 实现 Runnable 接口的方式,实现接口的方式解决了Java中单继承的局限性。

方式三:
package com.atguigu.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class MyThread implements Callable<Integer>{

     @Override
     public Integer call() throws Exception{
          System.out.println("--------Callable" );
           return 200;
     }

     public static void main(String[] args) throws InterruptedException, ExecutionException{
        @SuppressWarnings({ "rawtypes", "unchecked" })
          FutureTask futureTask = new FutureTask( new MyThread());
           new Thread(futureTask).start();

           System.out.println("返回参数:"+futureTask.get());
     }
}
说明:Runnable和Callable的区别?
     ① Callable需要实现call方法,而Runnable需要实现run方法;
     ② call方法还可以返回任何对象,无论是什么对象,JVM都会当作Object来处理,而Runnable没有返回结果。
     ③ Callable能够抛出checked exception,而Runnable不可以。
     ④ Runnable是自从java1.1就有了,而Callable是1.5之后才加上去的
     ⑤ Callable和Runnable都可以应用于executors。而Thread类只支持Runnable.

7.线程的生命周期:

(1) 线程运行状态说明:
新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状    态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
    等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
    其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。 
(2) 线程错误的停止方法:在开发当中不可使用Stop()方法,已经过时,因为该方法具有不安全性;
     线程正确的停止方法:使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。通过boolean循环控制程序的开始和结束
(3) 线程错误的中断方法:interrupt() 不能用于中断线程,在调用interrupt方法后, sleep方法抛出异常,然后输出错误信息:sleep interrupted.所以不使用
     线程正确的中断方法 :使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。通过boolean循环控制程序的开始和结束  
public class HelloThread1 implements Runnable{
     int i = 0;
     public static boolean flag = true;
     
     public void setFlag(){
         flag = false;
     }
     
     @Override
     public void run() {
         while(flag){
              System.out.println(i++);
         }
     }
}
/*
 * 结束线程 : 通常在线程执行体中写一些循环语句,因此控制住了循环,就相当于控制住了线程,即通知方式
 */
public class HelloThread1 {
     public static void main(String[] args) throws Exception {

         HelloThread1 ht1 = new HelloThread1();
         Thread t1 = new Thread(ht1);
         t1.start();
         for (int i = 0; i < 100; i++) {
              System.out.println("+++++"+i);
              if(i==90){
                  ht1.setFlag();
                  System.out.println("控制从线程运行结束,此时主线程继续运行");
              }
         }
     }
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页