文章目录

  • 前言
  • 一、线程简介
    • 1.概述
    • 2.进程、线程 区别
    • 在这里插入图片描述
    • 3. 核心概念
  • 二、 线程创建
    • 1.概述
    • 2. 第一种方式继承Thread
      • 1) 继承Thread
      • 2) 示例:下载图片
    • 3. 第二种方式:实现Runnable
    • 5. 第三种方式:实现Callable
    • 5. Thread对比Runnable
    • 6. 线程示例
      • 1) 龟兔赛跑
      • 2) 12306购票
  • 三、静态代理和动态代理
    • 1. 静态代理
      • 1) 概述
      • 2) 示例
    • 2. 动态代理
      • 1) 概述
      • 2) 示例
  • 四、 lambda表达式创建进程
  • 五、 线程状态
    • 1. 概述
    • 2. 线程方法
      • 1) 线程停止
      • 2) Sleep()
        • a) 示例1 模拟12306 抢票
      • 3) Join()方法
      • 4) Yield()
      • 5) Priority
      • 6) Daemon()
    • 3. 常用其他方法

前言

之前在学校学习线程,就是很简单的学习创建和使用,一般也没用过线程,因为在学校根本用不到并发。线程的好处有很多:提高资源利用率,让电脑的资源充分利用起来;可以提高程序的运行速度;等等。
在公司,一般都会用到线程开发,juc的高并发开发、线程池的使用。一般这线都是在学校用不到也学不到的,所以我之前也没有搞过、学习过。所以我现在用到了,我就写个博客,记录一下,学习一下。
我想记录的东西有很多,也不知道能写多少,我尽力哈。

  • 线程基础
  • 线程状态
  • 线程同步
  • JUC高并发
  • 线程池

一、线程简介

1.概述

  • 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
  • 在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。
  • 线程是独立调度分派的基本单位。

简单一点解释

  • 方法间调用:普通方法调用,从哪里来到哪里去,闭合的一条路径。
  • 多线程使用:开辟了多条路径。

2.进程、线程 区别

区别 进程 线程
根本区别 作为资源分配的单位 调度和执行的单位
开销 每隔进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。 线程可以看成轻量级的进程,同一类线程共享赛马和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
所处环境 再操作系统中能同时运行多个任务(程序) 再同一应用中有多个顺序流同时执行
分配内存 系统再运行的时候会为每个进程分配不同的内存区域 除了CPU之外,不会为线程分配内存(线程所使用的资源是它所属的进程的资源),线程组只能共享资源
包含关系 没有线程的进程是可以被看作单线程的,如果一个进程内拥有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的。 线程是进程的一部分,所以线程有的时候被称为是清权进程或者轻量级进程

注意:很多多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是 模拟出来的多线程,即一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为 切换的很快,所以就有同时执行的错觉。

3. 核心概念

• 线程就是独立的执行路径;
• 在程序运行时,即使没有自己创建线程,后台也会存在多个线程, 如gc线程、主线程;
• main()称之为主线程,为系统的入口点,用于执行整个程序;
• 在一个进程中,如果开辟了多个线程,线程的运行由调度器安排 调度,调度器是与操作系统紧密相关的,先后顺序是不能人为的 干预的;
• 对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控 制;
• 线程会带来额外的开销,如cpu调度时间,并发控制开销
• 每个线程在自己的工作内存交互,加载和存储主内存控制不当会 造成数据不一致。

二、 线程创建

1.概述

线程创建有三种方式,如图所示:第三种实现Callable方式 是juc高级编程里的方式,目前只知道就可以啦。

2. 第一种方式继承Thread

1) 继承Thread

package com.feng.ch01_thread;
/*** 创建线程方式一:*  1. 创建:继承Thread + 重写run*  2. 启动: 创建子类对象 + start方法*/
public class StartThread extends Thread {@Overridepublic void run() {for (int i = 0 ; i<20; i++){System.out.println("一边唱歌");}}public static void main(String[] args) {// 创建子类对象StartThread startThread = new StartThread();// 启动startThread.start(); // 不保证立即运行, CPU 调用
//        startThread.run(); // 普通方法调用for (int i = 0; i< 20 ; i++){System.out.println("一遍coding");}}
}

2) 示例:下载图片

package com.feng.ch02_webdownload;public class ThreadDownload extends Thread {private String  url; //远程路径private String name; // 存储名字public ThreadDownload(String url, String name){this.url = url;this.name = name;}@Overridepublic void run() {WebDownloader webDownloader = new WebDownloader();webDownloader.download(url, name);System.out.println(name);}public static void main(String[] args) {ThreadDownload td01 = new ThreadDownload("http://article-fd.zol-img.com.cn/t_s500x2000/g1/M01/01/0F/ChMljV2C4SuIZfJoAABdiz-TYC8AAP2EQDL4VIAAF2j137.jpg", "phone.jpg");ThreadDownload td02 = new ThreadDownload("http://tblg.k-img.com/restaurant/images/Rvw/12277/12277487.jpg", "spl.jpg");ThreadDownload td03 = new ThreadDownload("http://thumbs.dreamstime.com/b/key-success-to-18466568.jpg", "success.jpg");td01.start();td02.start();td03.start();}
}

3. 第二种方式:实现Runnable

  1. 创建目标对象: IDownloader id =new IDownloader(“图片地址”,“baidu.png”);
  2. 创建线程对象+关联目标对象: Thread t =new Thread(id);
  3. 启动线程: t.start()
package com.feng.ch01_thread;
/*** 创建线程方式二:*  1. 创建:实现implement + 重写run*  2. 启动: 创建实现类对象 + Thread对象 + start方法**  推荐:避免单继承的局限性,优先使用接口*  方面共享资源*/
public class StartRunnable implements Runnable {@Overridepublic void run() {for (int i = 0 ; i<20; i++){System.out.println("一边唱歌");}}public static void main(String[] args) {/*// 创建实现类对象StartRunnable startThread = new StartRunnable();// 创建代理类对象Thread ch01_thread = new Thread(startThread);//启动ch01_thread.start();*/
// 链式写法new Thread(new StartThread()).start();for (int i = 0; i< 20 ; i++){System.out.println("一遍coding");}}
}

5. 第三种方式:实现Callable

  1. 创建目标对象: StartCallableDownload_simple cd =new StartCallableDownload_simple ();
  2. 创建执行服务: ExecutorService ser=Executors.newFixedThreadPool(3); // 3个线程
  3. 提交执行: Future result1 =ser.submit(cd1) ;
  4. 获取结果: boolean r1 =result1.get();
  5. 关闭服务: ser.shutdownNow();
package com.feng.ch04_callable;
import java.util.concurrent.*;
public class StartCallableDownload_simple implements Callable<Integer> {@Overridepublic Integer call() {System.out.println("name:"+Thread.currentThread().getName());return 0;}public static void main(String[] args) throws ExecutionException, InterruptedException {// 1、 创建目标对象StartCallableDownload_simple scd01 = new StartCallableDownload_simple();StartCallableDownload_simple scd02 = new StartCallableDownload_simple();StartCallableDownload_simple scd03 = new StartCallableDownload_simple();// 高级的juc 编程(java.util.concurrent),// 2、创建执行服务ExecutorService executorService = Executors.newFixedThreadPool(6);  // 6个线程// 3、提交执行Future<Integer> result01 = executorService.submit(scd01);Future<Integer> result02 = executorService.submit(scd02);Future<Integer> result03 = executorService.submit(scd03);// 4、获取结果   这里需要抛出 两个 异常Integer aBoolean = result01.get();Integer aBoolean1 = result02.get();Integer aBoolean2 = result03.get();System.out.println(aBoolean2);// 5、关闭服务executorService.shutdown();}
}

5. Thread对比Runnable

6. 线程示例

1) 龟兔赛跑

package com.feng.ch01_thread;/*** 模拟龟兔赛跑*/
public class RacerRunnable implements Runnable {public static void main(String[] args) {RacerRunnable racerRunnable = new RacerRunnable();new Thread(racerRunnable, "tortoise").start();new Thread(racerRunnable, "rabbit").start();}private String winner;// 胜利者@Overridepublic void run() {for (int step = 1; step <= 100; step++){// 模拟兔子休息if (Thread.currentThread().getName().equals("rabbit") && (step%10==0)){try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+"-->"+step);// 比赛是否结束boolean b = gameOver(step);if (b){break;}}}public boolean gameOver(int step){if (winner!=null){return true;}else{if (step == 100){winner = Thread.currentThread().getName();System.out.println("winner==>"+ winner);return true;}}return false;}
}

2) 12306购票

package com.feng.ch03_bugticket03;/*** 共享资源, 并发(线程安全)*/
public class Web12306 implements Runnable {// 票数private int ticketNums = 99;@Overridepublic void run() {while (true){if (ticketNums<0){break;}// 模拟网络延迟try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);}}public static void main(String[] args) {// 一份资源Web12306 web12306 = new Web12306();System.out.println(Thread.currentThread().getName());// 多份代理new Thread(web12306, "码畜").start();new Thread(web12306, "码农").start();new Thread(web12306, "码蟥").start();}
}


出现了负数和重复数据,则出现了 共享资源、线程安全 的问题。

三、静态代理和动态代理

概念:使用一个代理对象将对象包装起来,然后用该代理对象来取代该对象,任何对原始对象的调用都要通过代理,代理对象决定是否以及何时调用原始对象的方法

1. 静态代理

1) 概述

要求被代理类和代理类同时实现相应的一套接口,通过代理类调用重写接口的方法,实际上调用的是原始对象的同样的方法

Cilent调用Source的method()方法,实际上是Proxy来调用method()方法,静态代理中Source跟Proxy都要实现接口Sourceable。

2) 示例

首先是父接口 Animal.java

package com.feng.springboottest.other.staticproxy;public interface Animal {public void action();public void breath();}

Cat.java

package com.feng.springboottest.other.staticproxy;// 被代理的类
public class Cat implements Animal {@Overridepublic void action() {System.out.println("喵喵喵~~~~~~~");}@Overridepublic void breath() {System.out.println("喵式呼吸法~~~~~~~");}
}

CatProxy.java

package com.feng.springboottest.other.staticproxy;// 代理类
public class CatProxy implements Animal {//真正要代理的类Cat cat;public CatProxy(Cat cat) {this.cat = cat;}@Overridepublic void action() {System.out.println("==========catProxy 代理类执行开始!=============");//实质上在代理类中是调用了被代理实现接口的方法cat.action();System.out.println("==========catProxy 代理类执行结束!===========");}@Overridepublic void breath() {System.out.println("==========catProxy 代理类执行开始!=============");cat.breath();System.out.println("==========catProxy 代理类执行结束!===========");}
}

TestCatStaticProxy.java

package com.feng.springboottest.other.staticproxy;public class TestCatStaticProxy {public static void main(String[] args) {//被代理的类Cat,Cat实现了Animal接口Cat cat = new Cat();//代理类CatProxy,也实现了Animal接口CatProxy catProxy = new CatProxy(cat);//代理类来调用方法,实际上调用的是Cat的action(),breath()方法catProxy.action();catProxy.breath();}}

运行结果:

从运行结果可以看到其实执行的是被代理类的对象.
从这里我们会想,如果我想再创建一个Dog对象,又需要重新为Dog创建一个代理对象,如下:

public class Dog implements Animal {@Overridepublic void action() {System.out.println("汪汪汪~~~~~~~");}@Overridepublic void breath() {System.out.println("狗式呼吸法~~~~~~~");}
}
package com.feng.springboottest.other.staticproxy;public class DogProxy implements Animal {Dog dog;public DogProxy(Dog dog) {this.dog = dog;}@Overridepublic void action() {System.out.println("==========dogProxy 代理类执行开始!=============");//实质上在代理类中是调用了被代理实现接口的方法dog.action();System.out.println("==========dogProxy 代理类执行结束!===========");}@Overridepublic void breath() {System.out.println("==========dogProxy 代理类执行开始!=============");//实质上在代理类中是调用了被代理实现接口的方法dog.action();System.out.println("==========dogProxy 代理类执行结束!===========");}
}
package com.feng.springboottest.other.staticproxy;public class TestDogStaticProxy {public static void main(String[] args) {Dog dog = new Dog();DogProxy dogProxy = new DogProxy(dog);dogProxy.action();dogProxy.breath();}/*** 每次我要新加入一个实现Animal接口的对象的话,都要重新创建一个代理对象,这样会非常的麻烦,* 这其实是静态代理的缺点,动态代理*/}


每次我要新加入一个实现Animal接口的对象的话,都要重新创建一个代理对象,这样会非常的麻烦,
这其实是静态代理的缺点,
接下来就看 动态代理吧

2. 动态代理

1) 概述

动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象,下面直接看代码:

2) 示例

还是Animal.java

package com.feng.springboottest.other.staticproxy.dynamicproxy;public interface Animal {public void action();public void breath();
}

Cat

package com.feng.springboottest.other.staticproxy.dynamicproxy;// 被代理类
public class Cat implements Animal {@Overridepublic void action() {System.out.println("喵喵喵~~~~");}@Overridepublic void breath() {System.out.println("猫式呼吸法~~~~");}
}

Dog.java

package com.feng.springboottest.other.staticproxy.dynamicproxy;public class Dog implements Animal {@Overridepublic void action() {System.out.println("汪汪汪~~~~~");}@Overridepublic void breath() {System.out.println("狗式呼吸法~~~~");}
}

MyProxy.java

package com.feng.springboottest.other.staticproxy.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class MyProxy implements InvocationHandler {Object obj;public MyProxy() {}public MyProxy(Object obj) {this.obj = obj;}/***代理类调用方法时,都会调用invoke方法* @param proxy* @param method  代理对象执行的方法* @param args   参数* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("==============代理类开始执行!!!!=============");//returnVal是方法的返回值Object returnVal = method.invoke(obj, args);System.out.println("==============代理类执行结束!!!!=============");return returnVal;}
}

ProxyUtil.java

package com.feng.springboottest.other.staticproxy.dynamicproxy;import java.lang.reflect.Proxy;public class ProxyUtil {public static Object getProxyInstance(Object obj){MyProxy proxy = new MyProxy(obj);/**  obj.getClass().getClassLoader():被代理对象的类加载器*  obj.getClass().getInterfaces() :被代理对象 实现 的接口 (因为只有一个接口)*  proxy : 实现InvocationHandler的接口**  实质上是通过反射将 被代理类的加载器 和接口 与代理对象 关联起来*  obj :是被代理的对象*/return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), proxy);}
}

TestDynamicProxy.java

package com.feng.springboottest.other.staticproxy.dynamicproxy;import com.feng.springboottest.other.staticproxy.Cat;public class TestDynamicProxy {public static void main(String[] args) {Cat cat = new Cat();// 获取 代理类的 实例(通过反射)Object proxyInstance = ProxyUtil.getProxyInstance(cat);Animal animal = (Animal) proxyInstance;animal.action();animal.breath();Dog dog = new Dog();Object proxyInstance1 = ProxyUtil.getProxyInstance(dog);Animal animal1 = (Animal) proxyInstance1;animal1.action();animal1.breath();}
}

动态代理的代理对象是 在运行时动态创建目标类的代理对象,而静态代理是需要为每个目标类创建代理对象,动态代理只需要一个方法就可以,相比静态代理代码冗余量减少了。

四、 lambda表达式创建进程

从普通的thread实现 到jdk8的实现的转化,
从静态内部类-》局部内部类-》匿名内部类-》lambda表达式

package com.feng.ch06_lambdaThread;public class LambdaThread {// 第一次简化:静态内部类static class Test01 implements Runnable{@Overridepublic void run() {System.out.println("一边听歌");}}public static void main(String[] args) {new Thread(new Test01()).start();//第二次简化:局部内部类class Test02 implements Runnable{@Overridepublic void run() {System.out.println("一边看书");}}new Thread(new Test02()).start();// 第三次简化: 匿名内部类, 必须借助接口或者父类new Thread(new Runnable() {@Overridepublic void run() {System.out.println("一边coding");}}).start();// 第四次简化: jdk8 简化  lambda表达式new Thread(()->{System.out.println("一边学习");}).start();}
}

五、 线程状态

1. 概述

  1. 新生状态:一旦 Thread thread = new Thread();线程对象就进入了新生状态。
  2. 就绪状态:进入其状态的四个情况
    thread.start();
    解除阻塞中方法;
    thread.yield方法; 高风亮节,让出线程,让本线程进入就绪状态
    jvm切换,jvm将cpu从本地线程切换到其他线程。
  3. 运行状态:一定会从就绪状态被CPU调度到了,才会进行运行
  4. 堵塞状态:其发生的四个情况
    Thread.sleep();占着资源休眠。
    thread.wait(); 不占资源,站在一边等待。
    thread.join; 加入、合并、插队,等别人用完资源,在用。
    read 、write; 通过操作系统调用
  5. 死亡状态:
    stop(); 不推荐使用,不安全。过时。
    destroy();不推荐使用,不安全。过时。
    一般是让代码执行完,或者想方设法让代码执行完。设置标志。

2. 线程方法

  1. sleep ()
    • 使线程停止运行一段时间,将处于阻塞状态
    • 如果调用了sleep方法之后,没有其他等待执行的线程,这个时候当前线程不会马上恢复执行!
  2. join ()
    • 阻塞指定线程等到另一个线程完成以后再继续执行。 合并线程,也指插入线程。
  3. yield ()
    • 让当前正在执行线程暂停,不是阻塞线程,而是将线程转入就绪状态;
    • 调用了yield方法之后,如果没有其他等待执行的线程,此时当前线程就会马上恢复执行!
  4. setDaemon()
    • 可以将指定的线程设置成后台线程,守护线程;
    • 创建用户线程的线程结束时,后台线程也随之消亡;
    • 只能在线程启动之前把它设为后台线程
  5. setPriority(int newPriority) getPriority()
    • 线程的优先级代表的是概率
    • 范围从1到10,默认为5
  6. stop()停止线程
    • 不推荐使用

1) 线程停止

  • 不使用JDK提供的stop()/destroy()方法(它们本身也被JDK废弃了)。
  • 提供一个boolean型的终止变量,当这个变量置为false,则终止线程的运行。
package com.feng.state;/*** 终止线程* 1、线程正常执行完毕-->次数* 2、外部干涉 -->加入标识* 不要使用stop destroy**/
public class ch01_TerminateThread implements Runnable {//1、加入标识 标记线程体是否可以运行private boolean flag = true;private String name;public ch01_TerminateThread(String name) {this.name = name;}//3、对外提供方法改变标识public void terminate() {this.flag = false;}@Overridepublic void run() {int i=0;//2、关联标识,true-->运行 false -->停止while(flag) {System.out.println(name+"-->"+i++);}}public static void main(String[] args) {ch01_TerminateThread tt = new ch01_TerminateThread("C罗");new Thread(tt).start();for(int i=0;i<=99;i++) {if(i==88) {tt.terminate();//线程的终止System.out.println("tt game over");}System.out.println("main-->"+i);}}
}

2) Sleep()

拿住当前对象或者资源,进行占用而不使用,让 本身进程 和 其他消费该对象或者资源的进程 进入堵塞状态。这个特点是针对wait()方法而言。
这是一个静态方法,使用:Thread.sleep()。因为是 Thread,所以是当前的进程进行堵塞。
一般使用sleep()方法 进行模拟网络延时,在模拟网络延时的时候,放大了出现问题的概率。
• sleep(时间)指定当前线程阻塞的毫秒数;
• sleep存在异常InterruptedException;
• sleep时间达到后线程进入就绪状态;
• sleep可以模拟网络延时、倒计时等。
• 每一个对象都有一个锁,sleep不会释放锁;

a) 示例1 模拟12306 抢票

package com.feng.state;
/*** sleep模拟网络延时,放大了发生问题的可能性**/
public class ch02_BlockedSleep01 {public static void main(String[] args) {//一份资源Web12306 web =new Web12306();System.out.println(Thread.currentThread().getName());//多个代理new Thread(web,"码畜").start();new Thread(web,"码农").start();new Thread(web,"码蟥").start();}
}class Web12306 implements Runnable{//票数private int ticketNums = 99;@Overridepublic void run() {while(true) {if(ticketNums<0) {break;}//模拟延时try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"-->"+ticketNums--);}}
}

一般来说 资源只有一份,进程堵塞的时候,会加大出现问题的情况,会出现负数和重复的情况,这个问题使用线程同步或者锁来进程解决,下面会讲到。

3) Join()方法

Join() 称为合并线程,又称插入进程。让本线程直接到就绪状态等待CPU的调用,进而到运行状态,会让其他进程到堵塞状态。

package com.feng.state;public class ch07_BlockedJoin01 {public static void main(String[] args) {Thread t = new Thread(()->{for(int i=0;i<100;i++) {System.out.println(Thread.currentThread().getName()+i);}}) ;t.start();for(int i=0;i<100;i++) {if(i%20==0) {try {t.join();  //  线程插队 ,,main 被阻塞了} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName()+i);}}
}

4) Yield()

Yield() 称为礼让线程,也就是让当前正在执行的线程暂停。从行状态转入就绪状态。让cpu重新调度。
它也是一个静态方法,再那里调用,哪个线程就礼让当前进程。

package com.feng.state;public class ch05_YieldDemo01 {public static void main(String[] args) {new Thread(new MyYield(), "a").start();new Thread(new MyYield(), "b").start();}
}class MyYield implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+ "-->start");try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}Thread.yield(); // 礼让System.out.println(Thread.currentThread().getName()+ "-->end");}}

5) Priority

Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调 度器按照线程的优先级决定应调度哪个线程来执行。 线程的优先级用数字表示,范围从1到10
• Thread.MIN_PRIORITY = 1
• Thread.MAX_PRIORITY = 10
• Thread.NORM_PRIORITY = 5 使用下述方法获得或设置线程对象的优先级。
• int getPriority();
• void setPriority(int newPriority);
优先级的设定建议在start()调用前
注意优先级低只是意味着获得调度的概率低。并不是绝对先调用优先级高后调 用优先级低的线程。

package com.feng.state;
/*** 线程的优先级 1-10* 1、NORM_PRIORITY  5 默认* 2、MIN_PRIORITY   1* 2、MAX_PRIORITY  10* 概率 ,不代表绝对的先后顺序**/
public class ch10_PriorityTest {public static void main(String[] args) {System.out.println(Thread.currentThread().getPriority());MyPriority  mp = new MyPriority();Thread t1 = new Thread(mp,"adidas");Thread t2 = new Thread(mp,"NIKE");Thread t3 = new Thread(mp,"回力");Thread t4 = new Thread(mp,"李宁");Thread t5 = new Thread(mp,"双星");Thread t6 = new Thread(mp,"puma");//设置优先级在启动前t1.setPriority(10);t2.setPriority(Thread.MAX_PRIORITY);t3.setPriority(Thread.MAX_PRIORITY);t4.setPriority(Thread.MIN_PRIORITY);t5.setPriority(Thread.MIN_PRIORITY);t6.setPriority(Thread.MIN_PRIORITY);t1.start();t2.start();t3.start();t4.start();t5.start();t6.start();}
}
class MyPriority implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());Thread.yield(); // 礼让线程,将线程 返回到就绪状态。}
}

6) Daemon()

package com.feng.state;public class ch11_DaemonTest {public static void main(String[] args) throws InterruptedException {Thread t =new Thread(new God(),"God");t.setDaemon(true);//将用户线程调整为守护// 执行守护线程t.start();// 执行用户线程Thread.sleep(Long.parseLong("1000"));new You().start();}
}
class You extends Thread{@Overridepublic void run() {Thread.currentThread().setName("You");for(int i=1;i<=5;i++) {System.out.println("happy life...");}System.out.println(Thread.currentThread().getName()+":finish");}
}
class God implements Runnable{@Overridepublic void run() {for(;true;) {System.out.println(Thread.currentThread().getName()+":bless you");}}
}

3. 常用其他方法


方法 功能
isAlive() 判断线程是否还活着,即线程是否还未终止
setName() 给线程起一个名字
getName() 获取线程的名字
currentThread() 取得当前正在运行的线程对象,也就是获取自 己本身

这几个方法,上面都演示过,就不单单演示啦,都很常用。

接下来就是线程同步、线程协作:生产者消费者模式、高级主题。直接进入博客列表即可看到

java多线程学习一、线程介绍、线程创建的3种方式、lambda创建方式、线程状态、线程示例:12306买票和银行取钱相关推荐

  1. java多线程学习二、安全与不安全示例:12306买票和银行取钱、java内存模型、内存可见性、线程同步块和方法

    文章目录 前言 1. 什么是块,分为几种 2. 静态块与构造块的区别 一. 举例说明:并发情况下,线程不安全 1. 示例1:unsafe12306取票 2. 示例2:unsafe银行取钱 二.线程不安 ...

  2. java线程学习,GitHub - zksir/thread: Java多线程学习

    Java多线程学习 threadcoreknowledge包----线程核心知识基础 createthreads包 创建线程 1.实现多线程的方法是1种还是2种还是4种? Oracle官方:2种,一种 ...

  3. Java多线程学习处理高并发问题

    在程序的应用程序中,用户或请求的数量达到一定数量,并且无法避免并发请求.由于对接口的每次调用都必须在返回时终止,因此,如果接口的业务相对复杂,则可能会有多个用户.调用接口时,该用户将冻结. 以下内容将 ...

  4. java多线程学习-java.util.concurrent详解

    http://janeky.iteye.com/category/124727 java多线程学习-java.util.concurrent详解(一) Latch/Barrier 博客分类: java ...

  5. Java多线程学习(二)synchronized关键字(1)

    转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...

  6. java多线程学习笔记。

    java多线程学习笔记 线程的优缺点: 多线程的好处: 充分利用多处理核心,提高资源的利用率和吞吐量. 提高接口的响应效率,异步系统工作. 线程的风险: 安全危险(竞争条件):什么坏事都没有发生.在没 ...

  7. 【转】Java 多线程学习

    原网址:https://www.cnblogs.com/yjd_hycf_space/p/7526608.html Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实J ...

  8. 转:Java多线程学习(总结很详细!!!)

    Java多线程学习(总结很详细!!!) 此文只能说是java多线程的一个入门,其实Java里头线程完全可以写一本书了,但是如果最基本的你都学掌握好,又怎么能更上一个台阶呢? 本文主要讲java中多线程 ...

  9. Java多线程学习——01

    Java多线程学习--01 1.核心概念 程序:是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念 进程Process:是执行程序的一次执行过程,它是一个动态的概念,是系统资源分配的单 ...

最新文章

  1. ValueTransformer
  2. 对信噪比SNR、EbN0、EsN0的个人详细理解
  3. GIS实战应用案例100篇(二)-元胞自动机模拟城市扩张过程
  4. php string slice,substring()与str.slice()区别
  5. css中hover的妙用!!
  6. 机器学习_贝叶斯算法
  7. PN序列的产生以及相关函数的计算
  8. 微信小程序弹框种类汇总
  9. 我的Windows Server 2008激活
  10. EXCEL功能之Excel表格边框设置
  11. 移动硬盘插入电脑后不显示盘符
  12. 【OpenGL】用GLFW和glad创建窗口
  13. 物理量与单位符号的书写标准
  14. 2022-2028年中国中频加热设备行业市场发展调研及未来前景规划报告
  15. 如何做IT项目PoC测试
  16. python求逆矩阵的方法,Python 如何求矩阵的逆
  17. 停车场web项目(内含有数据库)
  18. Ectiture impossible,doublon dans une cle de la错误
  19. Ribbon与Hystrix
  20. (原创)使用AsyncTask(带修改线程池方式)+自定义ImageLoader+LRU算法对图片三级缓存及其显示优化(只有在ListView滑动停止的时候才去网络请求获取图片数据)

热门文章

  1. 【深度学习】MTCNN总结
  2. 利用Python编写一个高斯正反算程序
  3. 我国姓氏历史源远流长,这些形形色色的姓氏是如何产生的?
  4. 四旋翼无人机学习之准备篇(一)
  5. str的charCodeAt()用法
  6. centos设置BOOTPROTO none和dhcp有什么区别
  7. 云麦 体脂称 华为 哪个好_现在市面上的体脂称哪个牌子的最好?
  8. 第49章 AutoMapper深入理解
  9. 5种数据压缩算法实现和性能测试
  10. 笔记本玩游戏限30帧的解决办法