1、线程

1、概述

     宏观来讲
     进程:就是正在运行的程序
     线程:就是进程的执行路径,执行单元

2、创建并启动线程的两种方式(掌握)
     1、定义一个类继承Thread类
  1. package cn.itcast.createThread;
  2. class MyThread extends Thread{
  3. @Override
  4. public void run() {
  5. System.out.println("线程在运行");
  6. }
  7. }
  8. public class Demo1 {
  9. public static void main(String[] args) {
  10. MyThread mt = new MyThread();
  11. //启动线程
  12. mt.start();
  13. }
  14. }

     2、定义一个类实现Runnable接口,并且重写run()方法
  1. package cn.itcast.createThread;
  2. class MyRunnable implements Runnable {
  3. @Override
  4. public void run() {
  5. System.out.println("启动了");
  6. }
  7. }
  8. public class Demo {
  9. public static void main(String[] args) {
  10. //第一步:创建实现了Runnable接口的子类对象
  11. MyRunnable mr = new MyRunnable();
  12. //第二步:通过刚创建的mr对象创建Thread对象
  13. Thread thread = new Thread(mr);
  14. //第三步:启动线程
  15. thread.start();
  16. }
  17. }

3、给线程设置名字(掌握)
    1、通过Thread类的有参构造
    2、通过Thread类的setName方法
    3、通过Thread.currentThread().setName()方法
  1. public class MyThread extends Thread{
  2. @Override
  3. public void run() {
  4. //设置线程名
  5. Thread.currentThread().setName("线程A");
  6. System.out.println(Thread.currentThread().getName());
  7. }
  8. public static void main(String[] args) {
  9. MyThread mt = new MyThread();
  10. mt.start();
  11. }
  12. }
  1. package cn.itcast.create;
  2. public class MyRunnable implements Runnable{
  3. @Override
  4. public void run() {
  5. //设置线程名
  6. Thread.currentThread().setName("线程A");
  7. System.out.println(Thread.currentThread().getName());
  8. }
  9. public static void main(String[] args) {
  10. Thread t = new Thread(new MyRunnable());
  11. t.start();
  12. }
  13. }



4、获取线程的名字(掌握)
    1、通过Thread类的getName方法
    2、通过Thread.currentThread().getName()方法

5、线程的随机性原理
     多个程序实际是通过CPU在做高效切换实现的

6、线程的声明周期(了解)
     新建 --> 就绪 --> 运行 -->阻塞 --> 死亡
     
     这里要注意,线程阻塞后就无法执行,回到就绪状态


2、卖票案例(掌握)

1、有问题的代码(出现错误票)

  1. /**
  2. 卖票程序
  3. */
  4. public class TicketRunnable implements Runnable{
  5. private int tickets = 100;
  6. @Override
  7. public void run() {
  8. while(true){
  9. if(tickets > 0){
  10. try {
  11. Thread.sleep(1000);//必须加这个,由于CPU太快否则不一定出现负数-----语句1
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张的票");---语句2
  16. }else{
  17. break;//必须加这个,否则无法跳出循环,造成死机
  18. }
  19. }
  20. }
  21. }
  22. /**
  23. 测试类
  24. */
  25. public class TicketDemo {
  26. public static void main(String[] args) {
  27. TicketRunnable runnable = new TicketRunnable();
  28. Thread t1 = new Thread(runnable, "窗口1");
  29. Thread t2 = new Thread(runnable, "窗口2");
  30. Thread t3 = new Thread(runnable, "窗口3");
  31. t1.start();
  32. t2.start();
  33. t3.start();
  34. }
  35. }

2、产生问题的原因
     比如现在只剩一张票了tickets=1,现在有两个线程,线程1和线程2
     线程1先执行,判断tickets >0,执行线程1的语句1,然后被休眠1s
     在这个时候线程2抢到了执行权,首先判断tickets>0,继续往下走,执行线程2的语句1,然后被休眠1秒
     在线程2休眠的时候,线程1醒了,执行语句1,然后线程1停止,这时候tickets=0
     线程2醒了,执行语句2,这时候tickets=-1


3、如何查找问题(掌握)
     1、看有没有共享数据
     2、看操作共享数据的语句是不是多条语句
     3、看是不是在多线程的环境中

     最后,把操作共享数据的多条语句用 锁起来,注意我们的这把锁必须被多个线程所共享

4、修改后的代码(掌握)
  1. 修改后的代码/卖票案例完整代码
  2. public class TicketRunnable implements Runnable {
  3. private int tickets = 50;
  4. private Object lock = new Object();
  5. @Override
  6. public void run() {
  7. while (true) {
  8. synchronized (lock) {
  9. if (tickets > 0) {
  10. try {
  11. Thread.sleep(100);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. System.out.println(Thread.currentThread().getName()+ "正在卖第" + tickets-- + "张的票");
  16. } else {
  17. break;
  18. }
  19. }
  20. }
  21. }
  22. }

3、锁,同步代码块,同步方法(这块记住结论就好,根据自身情况自行测试)

1、同步代码块
     synchronized(锁对象){
          需要被锁的代码//线程只有拿到了锁对象,才能执行这里的代码!!!换言之,这里的代码如果执行了,说明该线程拿到了锁对象,其他线程不能拿到该锁对象
     }

     注意
          多个线程必须使用同一个锁对象,要不然锁无效

2、同步方法(掌握)
     public synchronized void show(){}               //普通方法的锁是this
     public static synchronized void show(){}    //静态方法的锁是当前类的字节码文件对象 类名.class

3、注意问题(掌握)
     多个线程必须使用同一个锁对象,要不然锁无效
     同步代码块锁可以是任意对象
     同步方法的锁是this
     静态方法的锁是当前类的字节码文件对象 类名.class 

4、什么时候用同步代码块,什么时候用同步方法
     尽可能用同步代码块
     如果一个方法内的所有代码都被同步代码块包住了,那就用同步方法就可以了

4、死锁(掌握)

死锁原因总结
     线程1自身拿着一个锁:A锁,线程2自身拿着一个锁:B锁
     当线程1要用B锁,线程B要用A锁的时候就会发生死锁
  1. /**锁对象*/
  2. public class Lock {
  3. public static final Object LOCK_A = new Object();
  4. public static final Object LOCK_B = new Object();
  5. }
  6. /**线程1*/
  7. public class Thread1 extends Thread {
  8. @Override
  9. public void run() {
  10. synchronized (Lock.LOCK_A) {
  11. System.out.println("我是线程1,已经拿到A锁,将要去哪B锁");
  12. synchronized (Lock.LOCK_B) {
  13. System.out.println("我是线程1,成功拿到B锁");
  14. }
  15. }
  16. }
  17. }
  18. /**线程2*/
  19. public class Thread2 extends Thread {
  20. @Override
  21. public void run() {
  22. synchronized (Lock.LOCK_B) {
  23. System.out.println("我是线程2,已经拿到B锁,将要去哪A锁");
  24. synchronized (Lock.LOCK_A) {
  25. System.out.println("我是线程2,成功拿到A锁");
  26. }
  27. }
  28. }
  29. }
  30. /**测试代码*/
  31. public class Test {
  32. public static void main(String[] args) {
  33. Thread1 t1= new Thread1();
  34. Thread2 t2= new Thread2();
  35. t1.start();
  36. t2.start();
  37. }
  38. }
  39. //注意:以上代码可能不会死锁,如果必须产生死锁效果将run()方法中的所有内容用while(true)包裹起来

5、休眠线程(掌握)

Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000

  1. package cn.itcast.createThread;
  2. public class MyThread extends Thread{
  3. @Override
  4. public void run() {
  5. try {
  6. Thread.sleep(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }

6、守护线程

setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出
  1. package cn.itcast.createThread;
  2. public class MyThread extends Thread{
  3. @Override
  4. public void run() {
  5. while(true){
  6. System.out.println("xx");
  7. }
  8. }
  9. public static void main(String[] args) throws Exception {
  10. MyThread mt = new MyThread();
  11. mt.setDaemon(true);
  12. mt.start();
  13. //主线程在1S后结束,结束后mt线程也随之停止
  14. Thread.sleep(1000);
  15. }
  16. }

7、加入线程

  1. package cn.itcast.createThread;
  2. public class MyThread extends Thread{
  3. @Override
  4. public void run() {
  5. while(true){
  6. System.out.println("xx");
  7. }
  8. }
  9. public static void main(String[] args) throws Exception {
  10. MyThread mt = new MyThread();
  11. mt.start();
  12. mt.join();
  13. //因为mt线程被设置为加入线程,所以只有当mt线程执行完后你好才会执行
  14. System.out.println("你好");
  15. }
  16. }


8、设置线程优先级

1、线程优先级级别

线程默认优先级是5。范围是1-10

     Thread.MAX_PRIORITY         //10
     Thread.MIN_PRIORITY         //1
     Thread.NORM_PRIORITY     //5

2、方法
     public final int getPriority():获取线程优先级
     public final void setPriority(int newPriority):更改线程的优先级

3、注意
     优先级可以在一定的程度上,让线程获较多的执行机会

4、举例
     MyThread t = new MyThread();
     System.out.println(t.getPriority());
     t.setPriority(Thread.MAX_PRIORITY);



sleep(...) 线程休眠多久
join(..)  执行多久后就不插队了
wait(..) 多久后开始等待


13、今天必须掌握的内容,面试题,笔试题。(掌握这个就可以放心学习后面的知识了)

1、说说线程和进程
2、说说创建线程的两种方式,分别在什么情况下使用
3、如何启动线程
4、如何给线程设置名字,如何获取线程的名字
5、请描述下线程的生命周期
6、多个线程访问同一数据如果发生数据异常,我们应该如何查找问题,找到问题后应该如何处理
7、同步代码块的锁是什么,同步方法的锁是什么,静态同步方法的锁是什么
8、说说死锁原理
9、如何让线程进入休眠状态
10、sleep和wait的区别(都释放CPU执行权,sleep不释放锁,wait释放锁)
11、一个线程的优先级越高,那么这个线程就一定先执行完毕其他线程才能执行,错还是对,为什么
12、代码题:卖票案例,增加需求:统计每个窗口各卖了多少张票。(分别用线程的两种方式实现)
13、代码题:死锁案例









Day24_多线程第一天的更多相关文章

  1. “全栈2019”Java多线程第一章:认识多线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. 秒杀多线程第一篇 多线程笔试面试题汇总 ZZ 【多线程】

    http://blog.csdn.net/morewindows/article/details/7392749 系列前言 本系列是本人参加微软亚洲研究院,腾讯研究院,迅雷面试时整理的,另外也加入一些 ...

  3. 5天不再惧怕多线程——第一天 尝试Thread

    随笔 - 218  文章 - 1  评论 - 3819 5天不再惧怕多线程——第一天 尝试Thread   原本准备在mongodb之后写一个lucene.net系列,不过这几天用到多线程时才发现自己 ...

  4. Java学习多线程第一天

    内容介绍 Thread 线程创建 线程池 线程状态图 1 多线程 1.1     多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念. 进程:进程指正在运行的程序.确切的来说,当一个程序 ...

  5. Abap 多线程

    http://scn.sap.com/thread/18844     SAP ABAP 实现多线程 第一步:初始化server group ,server group 可以用RZ12进行维护,参数支 ...

  6. 跟着刚哥梳理java知识点——多线程(十六)

    创建多线程第一种方式:① 继承:继承Thread.② 重写:重写Thread类的run()方法③ 创建:创建一个子类的对象④ 调用:调用线程的start()方法,启动此线程,调用run()方法 cla ...

  7. Java 多线程(一)—— 概念的引入

      并发和并行 并行:指两个或多个时间在同一时刻发生(同时发生): 并发:指两个或多个事件在一个时间段内发生. 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 C ...

  8. 多线程之 Thread类

    一.多线程第一种方式的实现步骤(继承Thread类) 代码演示: 1.定义MyThread类,继承Thread类 2.重写了里面的run方法,在run方法中定义线程要执行的任务 public clas ...

  9. 收藏:c语言的多线程同步

    1.<秒杀多线程第一篇 多线程笔试面试题汇总> 2.<秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别> 3.<秒杀 ...

随机推荐

  1. .NET截取指定长度汉字超出部分以"..."代替

    /// <summary> /// 将指定字符串按指定长度进行剪切, /// </summary> /// <param name= "oldStr " ...

  2. BZOJ 1189 二分匹配 || 最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1155  Solved: 420[Submi ...

  3. C#中Thread与ThreadPool的比较

    最近同事在编写一个基于UPD RTP协议的通信软件,在处理接收Listen时,发现了一个问题到底是用Thread还是ThreadPool呢? 我看同事的问题比较有典型性,还是做以整理培训一下吧 Thr ...

  4. C#自定义属性(跟成员变量的区别)

    属性声明 public int age { get; set; } 从功能上等价于 private int m_age; public int age {get { return m_age; }se ...

  5. PowerMockito 同时mock多个对象

    有时候,需要测试的方法内有collections结构,就需要同时mock多个对象 被测方法: public class EmployeeService { public List<Integer ...

  6. cisco vpn client 自动登陆脚本

    cisco vpn client 不能保存密码,每次都要输入太麻烦了 写了个wsh,可以自动输入密码,并登陆 '需要一个好听的名字 <job id="cisco"> ' ...

  7. EF实体框架数据操作基类(转)

    //----------------------------------------------------------------// Copyright (C) 2013 河南禄恒软件科技有限公司 ...

  8. [DPDK][转]DPDK编程开发(4)—lcore

    1.知识百科 返回值 操作函数 函数功能 RTE_DECLARE_PER_LCORE (unsigned, _lcore_id) RTE_DECLARE_PER_LCORE (rte_cpuset_t ...

  9. GoLang 通过http Post获取数据

    func GetPostResponse(url, bodyType string, body *[]byte) (rdata []byte, err error) { b := bytes.NewB ...

  10. Android:Layout_weight的深刻理解

    最近写Demo,突然发现了Layout_weight这个属性,发现网上有很多关于这个属性的有意思的讨论,可是找了好多资料都没有找到一个能够说的清楚的,于是自己结合网上资料研究了一下,终于迎刃而解,写出 ...