Java多线程-Java多线程概述

第一章 Java多线程概述

  • 线程的启动
  • 线程的暂停
  • 线程的优先级
  • 线程安全相关问题

1.1 进程与线程

进程:可以将运行在内存中的程序(如exe文件)理解为进程,进程是受操作系统管理的基本的运行单元。

线程:可以理解为进程中独立运行的子任务。如果QQ.exe运行时的好友视频线程、下载文件线程、数据传输线程、发送消息线程等。

使用多线程可以更好的利用计算机的资源如CPU。线程被调用的时机是随机的。

1.2 Java多线程实现方式

1.2.1 继承Thread类

public class Thread implement Runnable

Thread 类实现了Runnable接口,它们之间具有多态关系。重新run方法,方法内编写执行任务的代码。启动线程后会调用run方法。当run方法执行结束后,线程也会跟着终止。

我们需要在主程序中使用Thread类的start方法启动新的线程。

  public class MyThread extends Thread{    @override     public void run(){                  System.out.println("新的线程!");            }  }  public class Main{     public static void main(String[] args){         MyThread t = new MyThread();          t.start();          System.out.println("主线程!");     }  } 

注:多次调用start方法会出现IllegalThreadStateException异常。

1.2.2 实现Runnable接口

继承Thread实现多线程有设计上的局限性,如果欲创建的线程类已经有一个父类,这是不能再继承Thread类了,java不支持多继承,所以可以实现Runnable接口。

  public class MyRunnable implements Runnable {     @override     public void run(){         System.out.println("运行中");     }  }

Thread类有两个构造器函数Thread(Runnable target)和Thread(Runnable target, String name)可以接收Runnable接口。

  public class Main{     public static void main(String[] args){      Runnable r = new MyRunnable();         Thread t = new Thread(r);          t.start();          System.out.println("主线程!");     }  } 

1.2.3 ThreadFactory启动线程

java.util.concurrent中包含一个将线程创建抽象化的ThreadFactory接口。利用该接口,可以将Runnable作为参数并通过new创建Thread实例的处理隐藏在ThreadFactory内部。默认的ThreadFactory对象是通过Executor.defaultThreadFactoy方法获取的。

  public class Main{     public static void main(String[] args){      ThreadFactory factory = Executor.defaultThreadFactoy;      Runnable r = new MyRunnable();         factory.newThread(MyRunnable).start();            }  } 

1.3 线程安全与锁

在共享数据的情况下即多个线程访问同一变量,可能存在线程安全问题。

通过在run方法前加入synchronized关键字,使得多个线程在执行run方法时排队进行处理。

synchronized可以在任意对象及方法上加上锁,加锁的到吗称为“互斥区”或“临界区”。

  public class MyThread extends Thread{    private int count = 5;   @override     synchronized public void run(){                      count--;     }  }

synchronized方法和synchronized代码块

  synchronized void method(){    ...  }  void method(){     synchronized(this){         ...     }  }

死锁:两个线程分别持有锁,并互相等待对方释放锁。

发生死锁的条件:

(1)存在多个sharedResource角色;

(2)线程持有某个SharedRosource角色锁的同时,还想获取其他SharedResource角色的锁;

(3)获取SharedResource角色的锁的顺序并不固定

1.4 停止线程

停止一个线程意味着在线程处理完任务之前停掉正在做的操作。虽然看起来非常简单,但是必须做好防范,以便达到预期的效果。停止一个线程可以使用Thread.stop()方法,但是最好不用它,已经被java高版本放弃。

大多数停止一个线程的操作使用Thread.interrupt()方法。

Java中三种停止正在运行线程的方法:

  • 设置退出标志变量,也就是当run方法完成后线程终止;
  • 使用stop方法,但不推荐;
  • 使用interrupt方法中断线程。

interrupt方法仅仅是在当前线程中打了一个停止标记,并不是真的停止线程。

  • this.interrupted():测试当前线程是否已经中断,执行后具有将状态标志清除为false的功能;
  • this.isInterrupted():线程线程Thread对象是否已经中断状态,但不清楚状态标志。

如果在sleep状态下停止一个线程,会进入catch语句,并且清楚停止状态值,使之变成false。

如果使用stop强制让线程停止则有可能使一些请理性的工作得不到完成。另外就是对锁定对象进行了解锁,导致数据得不到同步处理,出现数据不一致问题。

1.5 暂停线程

暂停线程意味着线程还可以恢复运行。java中使用suspend方法暂停线程,使用resume方法恢复线性。

使用suspend和resume方法如果使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象。

同时也容易出现数据不同步情况。

1.5 Thread相关方法

  • Thread.currentThread()方法可以返回当前线程信息,如Thread.currentThread().getName();
  • getId():获取线程唯一标识
  • sleep(long millis):将正在执行的线程休眠。

    sleep方法使当前线程(即调用该方法的线程)暂停执行一段时间,让其他线程有机会继续执行,但它并不释放对象锁。也就是说如果有synchronized同步快,其他线程仍然不能访问共享数据。注意该方法要捕捉异常。sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。

  • yield():方法的作用是放弃当前CPU资源,将它让给其他的任务去占用CPU执行时间。

    一个调用yield()方法的线程告诉虚拟机它乐意让其他线程占用自己的位置。这表明该线程没有在做一些紧急的事情。注意,这仅是一个暗示,并不能保证不会产生任何影响。并且yield方法只能让同优先级的线程有执行的机会。

  • wait()和notify()、notifyAll() :都是java.lang.Object的方法

    这三个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块内使用。synchronized关键字用于保护共享数据,阻止其他线程对共享数据的存取,但是这样程序的流程就很不灵活了,如何才能在当前线程还没退出synchronized数据块时让其他线程也有机会访问共享数据呢?此时就用这三个方法来灵活控制。

    wait()方法使当前线程暂停执行并释放对象锁标示,让其他线程可以进入synchronized数据块,当前线程被放入对象等待池中。当调用notify()方法后,将从对象的等待池中移走一个任意的线程并放到锁标志等待池中,只有锁标志等待池中线程能够获取锁标志;如果锁标志等待池中没有线程,则notify()不起作用。

    notifyAll()则从对象等待池中移走所有等待那个对象的线程并放到锁标志等待池中。

1.6 线程优先级

在操作系统中,线程可以划分优先级,优先级较高的线程的到CPU资源较多。

优先级的继承特性:如果A线程启动B线性,则AB优先级一样。

使用setPriority()可以设置优先级:java提供了三个变量MIN_PRIORITY、MAX_PRIORITY和NORM_PRIORITY

优先级较高的线程不一定每次都先执行完。

1.7 守护线程

java线程中有两种线程,一种是用户线程,另一种是守护线程。

当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线性就是垃圾回收线程。

原文地址:https://www.cnblogs.com/zhuweiheng/p/10465934.html

时间: 2024-10-11 03:40:49

Java多线程-Java多线程概述的相关文章

Java笔记五.多线程

Java中的多线程(一) 一.理解线程 1.进程.线程.多线程 1.进程:在多任务系统中,每个独立执行的程序(或说正在进行的程序)称为进程. 2.线程:一个进程中又可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索(一部分代码). 3.多线程:如果要一程序中实现多段代码同时交替运行,就需产生多个线程,并指定每个线程上所要运行的程序代码,即为多线程. 注:在单线程中,程序代码的执行是按调用顺序依次往下执行的,不能实现两端程序代码同时交替运行的效果.当我们的程序启动运行时,会自动产生一个

Java基础总结--多线程总结2

----多线程通信-----1.概述:多个线程处理同一个资源,但是各自的任务不相同eg:线程1负责存储数据,线程2负责处理该数据.数据--就是同一个资源怎样用java语言描述上面的例子:* 资源是变化的--数据是变化的--将其封装为对象* 存在两个任务不同的线程,需要2个run方法--所以封装在两个不同的线程类中* 必须保证输入和输出处理的是同一个对象-输入输出构造方法传参数(参数为资源对象引用)* 主函数里面,创建资源对象,线程类对象,启动线程2.多线程通信依然会出现线程安全的问题解决办法--

Java多线程——<八>多线程其他概念

一.概述 到第八节,就把多线程基本的概念都说完了.把前面的所有文章加连接在此: Java多线程——<一>概述.定义任务 Java多线程——<二>将任务交给线程,线程声明及启动 Java多线程——<三>简单的线程执行:Executor Java多线程——<四>让线程有返回值 Java多线程——<五>后台线程(daemon) Java多线程——<六>更方便的线程 Java多线程——<七>多线程的异常捕捉 均是个人理解和总结,代

3.8 java基础总结①多线程

多线程 多线程这章理论大于实践,因为在实际开发中多线程的都封装到框架里边了的,程序员一般不会写多线程,多线程属于Java里边比较底层的代码了. 线程是处理器调度的最基本单位程序>进程>线程程序是死的,当启动程序得时候会有一个或几个进程,每个进程里边可以有诺干线程.基于线程开销更 创建线程:两种方法1.声明Thread的子类,重写run方法class MyThread extends Thread{ public void run(){ }}Mythread a = new MyThread()

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

Java面试题-多线程

1. java中有几种方法可以实现一个线程? 多线程有两种实现方法,分别是继承Thread类与实现Runnable接口. 这两种方法的区别是,如果你的类已经继承了其它的类,那么你只能选择实现Runnable接口了,因为Java只允许单继承的. 2. 如何停止一个正在运行的线程? (1)方法1: 调用Thread.stop()方法停止线程. Thread.stop()不安全,已不再建议使用. 该方法天生是不安全的.使用thread.stop()停止一个线程,导致释放(解锁)所有该线程已经锁定的监视

Java中的多线程你只要看这一篇就够了

Java中的多线程你只要看这一篇就够了 引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其实只有一半对,因为反应"多角色"的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的"生产者,消费者模型". 很多人都对其中的一些概念不够明确,如同步.并发等等,让我

Java高级复习㈠ 多线程

1.线程 也称为轻量级进程,每个线程有自己的堆栈.程序计数器.局部变量.与进程相比,进程中的线程之间隔离程度要小 2.Java实现 ①implements Runnable ②extends Thread 一般推荐① 3.sleep().yield() sleep()方法对当前线程操作,指定以毫秒为单位的线程最小休眠时间,除非线程因中断提早恢复执行,否则不会在这段时间前恢复执行.线程可调用另一线程的interrupt()方法,向暂停的线程发出InterruptedException,变相唤醒暂停

[Android] 图片JNI(C++\Java)高斯模糊 多线程

在我的博客中,曾经发布了一篇高斯模糊(堆栈模糊)的文章:在其中使用了国外的一个堆栈模糊来实现对图片的模糊处理:同时弄了一个JNI C++ 的版本. 这篇文章依然是堆栈模糊:可以说最原始的地方还是堆栈模糊部分:只不过是支持多线程的. 纳尼??感情是之前那个不支持多线程?Sorry,我说错了:两个都是支持多线程调用的.不过新讲的这个是能在内部采用多线程进行分段模糊. 原来的:[Android]-图片JNI(C++\Java)高斯模糊的实现与比较 开工吧 说明:其中代码大部分来源于网络,不过都是开源的

为什么Java中实现多线程的方式有两种?

在面试的过程中,我们经常问被面试者,为什么Java中实现多线程的方式有两种(一种是直接继承Thread类,一种是实现Runnable接口)?可惜的是,很多面试者都答不出来,甚至从来没有想为什么.,那么真正的原因是什么呢?我们可以用反证法推理一下: 假设Java只提供Thread供大家继承从而实现多线程,考虑下面的一个需求,如果有一个已经继承了某个父类的类,但是这个类又想实现多线程,怎么办?很显然,如果只提供一个可以继承的类,肯定解决不了这个问题.那么,如何解决,毫无疑问,就只能使用接口了.