多线程

线程是什么?

一个线程是线程一个顺序执行流。

同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的栈堆。线程在切换时负荷小,因此,线程也被称为轻负荷进程。一个进程中可以包含多个线程。

线程什么时候使用?

线程通常用于在一个程序中需要同时完成多个任务的情况。我们可以将每个任务定义一个线程,使他们得以一同工作。

也可以用于在单一线程中可以完成,但是使用多线程可以更快的情况。

线程创建

继承Thread类

  1. public class Thread implements Runnable

Thread 类实现了 Runnable 接口,它们之间具有多态关系。

其实,使用继承 Thread 类的方式实现多线程,最大的局限就是不支持多继承

  1. public class XC extedns Thread{
  2.  
  3. }

实现 Runnable 接口

语法:

  1. public class thread extends Object implements Runnale{
  2.  
  3. }

从 JDK 的 API 中可以发现,实质上 Thread 类实现了 Runnable 接口,其中的 run() 方法正是对 Runnable 接口中 run() 方法的具体实现。

继承 Thread 类的优缺点

当一个 run() 方法体现在继承 Thread 类中时,可以用 this 指向实际控制运行的 Thread 实例。因此,代码不需要使用以下控制语句:

  1. Thread.currenThread().sleep();

不再使用上面的控制语句,而是可以简单地使用 Threadsleep() 方法,继承 Thread 类的方式使代码变得简单易读。

实现 Runnable 接口的优缺点

从面向对象的角度来看,Thread 类是一个虚拟处理机严格的封装,因此只有当处理机模型修改或扩展时,才应该继承该类。由于 Java 技术只允许单一继承,因此如果已经继承了 Thread 类,就不能再继承其他任何类,这会使用户只能采用实现 Runnable 接口的方式创建线程。

实例:

  1. /**
  2. * 线程创建
  3. * 2种方式:
  4. * 继承 Thread类
  5. * 实现接口 Runnable
  6. * @author soft01
  7. *
  8. */
  9. //class Xc extends Thread{//创建线程所需要继承的的类
  10. // public void run() {//run方法是覆盖父类方法
  11. // for(int i=0;i<20;i++) {
  12. // System.out.println("111");
  13. // }
  14. // }
  15. //}
  16. class Xc2 implements Runnable{//不是继承类,而改成了实现接口
  17. public void run() {//run方法是覆盖父类方法
  18. for(int i=0;i<20;i++) {
  19. System.out.println("111");
  20. }
  21. }
  22. }
  23. public class One {
  24. public static void main(String[] args) {
  25. // Xc xc=new Xc();
  26. // xc.run();
  27. // xc.start();
  28. /**
  29. * 谁调用start方法,程序就去自动调用run方法
  30. * start 会单开启一个线程,而不是直接调用。
  31. */
  32. Xc2 xc2=new Xc2();
  33. Thread a=new Thread(xc2);
  34. a.start();
  35. for(int i=0;i<20;i++) {
  36. System.out.println("222");
  37. }
  38. }
  39.  
  40. }

对线程生命周期中的 7 种状态做说明。

  1. 出生状态:用户在创建线程时所处的状态,在用户使用该线程实例调用 start() 方法之前,线程都处于出生状态。
  2. 就绪状态:也称可执行状态,当用户调用 start() 方法之后,线程处于就绪状态。
  3. 运行状态:当线程得到系统资源后进入运行状态。
  4. 等待状态:当处于运行状态下的线程调用 Thread 类的 wait() 方法时,该线程就会进入等待状态。进入等待状态的线程必须调用 Thread 类的 notify() 方法才能被唤醒。notifyAll() 方法是将所有处于等待状态下的线程唤醒。
  5. 休眠状态:当线程调用 Thread 类中的 sleep() 方法时,则会进入休眠状态。
  6. 阻塞状态:如果一个线程在运行状态下发出输入/输出请求,该线程将进入阻塞状态,在其等待输入/输出结束时,线程进入就绪状态。对阻塞的线程来说,即使系统资源关闭,线程依然不能回到运行状态。
  7. 死亡状态:当线程的 run() 方法执行完毕,线程进入死亡状态。

提示:一旦线程进入可执行状态,它会在就绪状态与运行状态下辗转,同时也可能进入等待状态、休眠状态、阻塞状态或死亡状态。

线程优先级

 线程的切换是由线程调度控制的,我们可以通过代码来干涉,但是我们可以通过提高线程的优先级来最大程度的改善线程获取时间片的几率。

线程的优先级被划分为10级,值分别为1-10,其中1最低,10最高。线程提供了3个常量来表示最低,最高,以及默认优先级:

  1. Thread.MIN_PRIORITY,
  2.  
  3. Thread.MAX_PRIORITY,
  4.  
  5. Thread.NORM_PRIORITY

线程同步

synchronized关键字

多个线程并发读写同一个临界时会发生“线程并发安全问题”

比如:

多线程共享实例变量

多线程共享静态公共变量

若要解决线程安全问题,需要将异步的操作变为同步操作。

异步操作:多线程并发的操作,相当于各干各的。

同步操作:有先后顺序的操作,相当于你完成后我在干。

synchronized关键字是java中的同步锁

线程休眠

sleep()方法的作用是在指定的毫秒数内让当前正在执行的线程“休眠”(暂停)

实例:

  1. //线程睡眠
  2. public class Four {
  3. public static void main(String[] args) {
  4. Xc5 xc5=new Xc5();
  5. Thread c=new Thread(xc5);
  6. c.start();
  7. }
  8. }
  9. class Xc5 implements Runnable{
  10. public void run() {//throws Exception
  11. for(int i=0;i<2;i++) {
  12. System.out.println(Thread.currentThread().getName()+""+i);
  13. try {
  14. Thread.sleep(1000);//毫秒
  15. System.out.println("结束时间"+System.currentTimeMillis());
  16. }catch(Exception e) {
  17.  
  18. }
  19. }
  20. }
  21. }
  22.  
  23. //class Yy implements Runnable{
  24. // public void run() throws Exception{
  25. //
  26. // }
  27. //}
  28. //class Xx extends Thread{
  29. // public void run() throws Exception{
  30. //
  31. // }
  32. //}
  33. /**
  34. * 用throws抛异常的时候,如果向主调处抛异常的方法是从父类继承的
  35. * 或者从接口实现的。那么,覆盖父类方法或实现接口时,如果父类中的原方法
  36. * 或接口中的原抽象方法没有抛异常,则子类覆盖父类的方法或实现接口的方法也不能抛异常
  37. * 而出现这种情况只能用try...catch,大不了catch中什么都不写
  38.  
  39. */

线程让步

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

实例:

  1. //线程让步
  2. public class Five {
  3. public static void main(String[] args) {
  4. Xc6 xc6=new Xc6();
  5. Thread a=new Thread(xc6);
  6. Thread b=new Thread(xc6);
  7. a.setName("线程一");
  8. b.setName("线程二");
  9. a.start();
  10. b.start();
  11. }
  12. }
  13. class Xc6 implements Runnable{
  14. public void run() {
  15. for(int i=0;i<=30;i++) {
  16. System.out.println(Thread.currentThread().getName()+""+i);
  17. if(i%1==0) {
  18. Thread.yield();
  19. }
  20. }
  21. }
  22. }

锁机制

Java提供了一种内置的锁机制来支持原子性:

同步代码块(synchronized关键字),同步代码块包含两部分:一个作为锁的对象的引用,一个作为由这个锁保护的代码块。

  1. synchronized (同步监视器——锁对象引用){
  2.  
  3. //代码块
  4.  
  5. }

 若方法所有代码都需要同步也可以给方法直接加锁。

每个Java对象都可以用做一个实现同步的锁,线程进入同步代码块之前会自动获得锁,并且在退出同步代码块时自动释放锁,而且无论是通过正常途径退出还是通过抛异常退出都一样,获得内置锁的唯一途径就是进入由这个锁保护的同步代码块或方法。

选择合适的锁对象

使用synchroinzed需要对一个对象上锁以保证线程同步。那么这个锁对象应当注意:

多个需要同步的线程在访问该同步块时,看到的应该是同一个锁对象引用。否则达不到同步效果。

通常我们会使用this来作为锁对象。

选择合适的锁范围

 在使用同步块时,应当尽量在允许的情况下减少同步范围,以提高并发的执行效率。

静态方法锁

方法加锁:

  1. public synchronized void xxx(){
  2.  
  3. }

那么该方法锁的对象是类对象。每个类都有唯一的一个类对象。获取类对象的方式:类名.class。

静态方法与非静态方法同时声明了synchronized,他们之间是非互斥关系的。原因在于,静态方法锁的是类对象而非静态方法锁的是当前方法所属对象。

synchronized 不仅可以用到同步方法,也可以用到同步块。对于同步块,synchronized 获取的是参数中的对象锁。

  1. synchronized(obj)
  2. {
  3. //代码
  4. }

实例:

  1. class CP implements Runnable{
  2. public static int chepiao=100;
  3. public static String aa=new String("1");//字符串随意定义,定义在函数上边
  4. //synchronized 作用是让它所管辖的代码部分,全部执行完否则全部不执行
  5. public void run()
  6. {//synchronized修饰函数不需要字符串,相当于默认是this
  7. while(true)
  8. {
  9. synchronized (aa)
  10. {//即可修饰代码块,又可以修饰函数
  11. if(chepiao>0)
  12. {
  13. System.out.println("第"+Thread.currentThread().getName()+"个车站正在卖第"+(101-chepiao)+"张");
  14. --chepiao;
  15. }
  16. else
  17. {
  18. break;
  19. }
  20. }
  21. }
  22. }
  23. }
  24. public class CP01 {
  25. public static void main(String[] args) {
  26. CP cp01=new CP();
  27. Thread cc=new Thread(cp01);
  28. CP cp02=new CP();
  29. Thread dd=new Thread(cp02);
  30. cc.start();
  31. dd.start();
  32. }
  33. }

Day04:异常处理(二) / 多线程基础的更多相关文章

  1. C#编程总结(二)多线程基础

    C#编程总结(二)多线程基础 无论您是为具有单个处理器的计算机还是为具有多个处理器的计算机进行开发,您都希望应用程序为用户提供最好的响应性能,即使应用程序当前正在完成其他工作.要使应用程序能够快速响应 ...

  2. Java 多线程基础(十二)生产者与消费者

    Java 多线程基础(十二)生产者与消费者 一.生产者与消费者模型 生产者与消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”.“消费者”.“仓库”和“产品”.他们之间的关系如下: ①.生 ...

  3. Java多线程基础知识例子

    一.管理 1.创建线程 Thread public class Main { public static void main(String[] args) { MyThread myThread = ...

  4. Java多线程基础知识笔记(持续更新)

    多线程基础知识笔记 一.线程 1.基本概念 程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程序的一次执行过程,或是 ...

  5. Java基础知识笔记(四:多线程基础及生命周期)

    一.多线程基础 编写线程程序主要是构造线程类.构造线程类的方式主要有两种,一种是通过构造类java.lang.Thread的子类,另一种是通过构造方法实现接口java.lang.Runnable的类. ...

  6. Java多线程干货系列—(一)Java多线程基础

    前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程:进程中负责程序执行的 ...

  7. JAVASE02-Unit09: 多线程基础

    Unit09: 多线程基础 * 线程 * 线程用于并发执行多个任务.感官上像是"同时"执行 *  * 创建线程有两种方式. * 方式一: * 继承线程并重写run方法来定义线程要执 ...

  8. Java多线程干货系列(1):Java多线程基础

    原文出处: 嘟嘟MD 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要,下面跟我一起开启本次的学习之旅吧. 正文 线程与进程 1 线程 ...

  9. 多线程基础(五)NSThread线程通信

    5.多线程基础 线程间通信   什么叫线程间通信 在一个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信   线程间通信的体现 1个线程传递数据给另一个线程 在1个线程中执行完特定任务后, ...

随机推荐

  1. tar命令--数据解档(三)解压.tar.gz文件报错 gzip:stdin:not in gzip format

    毕竟是生产..... 提示以下信息:  gzip: stdin: not in gzip format  tar: Child returned status 1  tar: Error is not ...

  2. 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) D. Delivery Delays (二分+最短路+DP)

    题目链接:https://codeforc.es/gym/101933/problem/D 题意:地图上有 n 个位置和 m 条边,每条边连接 u.v 且有一个距离 w,一共有 k 个询问,每个询问表 ...

  3. JS数组的交集、并集、差集,数组去重,获取两个数组重复的元素,去除两个数组相同的元素

    let arr1=[1,2,3,4,5,6] let arr2=[4,5,6,7,8,9] // 并集 数组去重 let RemoveSame=[...new Set([...arr1,...arr2 ...

  4. android&ios区别

    转自(只讲干货的老张) 面试中经常提问到一个点,就是做手机测试绕不去的点,那就是Android和ios的区别.这篇文章只做一些比较重要的点讲一下,太深入部分就不讲了,毕竟我做的是测试,而Android ...

  5. 将.py脚本打包成.exe

    https://www.cnblogs.com/wyl-0120/p/10823102.html 为了方便使用,通过pyinstaller对脚本进行打包成exe文件. pip3 install pyi ...

  6. 51nod1040 最大公约数之和,欧拉函数或积性函数

    1040 最大公约数之和 给出一个n,求1-n这n个数,同n的最大公约数的和.比如:n = 6时,1,2,3,4,5,6 同6的最大公约数分别为1,2,3,2,1,6,加在一起 = 15 看起来很简单 ...

  7. C++虚函数和成员函数内存 this指针问题

    father* p=new son; p->disp(...); 发现有好多人this指针的本质有错误的认识,估计不少人一说起this指针,脑袋立即反应出:那个类里使用的this指针,那么这个指 ...

  8. luogu3629

    P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...

  9. bzoj5457

    城市 HYSBZ - 5457 有n座城市,m个民族.这些城市之间由n-1条道路连接形成了以城市1为根的有根树.每个城市都是某一民族的聚居 地,Master知道第i个城市的民族是A_i,人数是B_i. ...

  10. MySQL初识数据库

    为什要用数据库 第一,将文件和程序存在一台机器上是很不合理的. 第二,操作文件是一件很麻烦的事 你可以理解为 数据库 是一个可以在一台机器上独立工作的,并且可以给我们提供高效.便捷的方式对数据进行增删 ...