1      多线程--初步

1进程

比如:QQ、迅雷、360、飞秋...

2线程的概念

3线程的意义:

4.Java程序的运行原理

代码是运行在线程中的,如果一个进程没有线程,那么进程就结束了,也就是说一个进程至少要有一个线程

当开启一个Java程序之后,在进程中至少会自动创建两个线程:主线程、垃圾回收线程

实际上,使用多线程并不是为了提高程序运行的速度,而是为了提高CPU的使用率

多线程:在进程中同时执行着多个执行路径,并且多个线程(执行路径)之间互不干扰

使用场景:

迅雷下载、360多个任务的执行、QQ视屏和文件传输………

for(int i=10;i<=100;i+=10){

System.out.println("洗衣服,进度"+i+"%");

Thread.sleep(500);

}

for(int i=0;i<=100;i+=10){

System.out.println("做饭,进度"+i+"%");

Thread.sleep(500);

}

//创建

WashThread wash = newWashThread();

CookThread cook = newCookThread();

//启动

wash.start();

cook.start();

for(inti=10;i<=100;i+=10){

System.out.println("微波炉加热,进度"+i+"%");

try {

Thread.sleep(500);

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

}

//每隔10秒打印Hello,同时可以接受用户输入,并打印出来

Scanner s = newScanner(System.in);

PrintThread t = newPrintThread();

t.start();

while(true){

String line =s.nextLine();

System.out.println(line);

}

//选择性学习

LagRunnable r = newLagRunnable();

ExecutorService service =Executors.newCachedThreadPool();

service.execute(r);

service.execute(r);

service.execute(r);

service.shutdown();

//**************************************

FileReader fr = newFileReader("g:/config.txt");

BufferedReader br = newBufferedReader(fr);

//               ReverseRunnable r =newReverseRunnable();

String name = br.readLine();

Class clz =Class.forName(name);

Runnable r=(Runnable)clz.newInstance();

//**************************************

//以上部分选择性学习,扩展内容

Thread t = new Thread(r);

t.start();

进程运行起来的程序

线程可以理解为一个子进程

进程间进行切换的代价较大,不能共享资源

线程间切换代价小,可以共享数据和逻辑

Java进程每运行一个java应用程序,就会启动一个虚拟机进程,我们的程序就在其中运行

Java线程每个java进程中都默认有一个主线程,名字为main

(我们之前的程序都是在主线程中执行)

Thread类java中的线程,在一个线程中的代码逻辑就像被一根线串起来一样,从前往后顺序执行的

,节省时间、避免程序阻塞带来的问题

分时复用多个线程不停地快速切换使用CPU,表面上看是同时执行,其实也是有先后顺序的,同一时间只有一个线程占有CPU。

创建-->就绪-->运行-->结束

运行-->阻塞--〉就绪

假如当前计算机只有一个CPU且只有一个核心,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令,那么Java是如何对线程进行调用的呢?

抢占调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取CPU时间片相对多一些

Java使用的是抢占式调度模型

优先级:获取CPU资源的几率

优先级越高的线程会获取越多的运行机会

优先级的取值范围是1-10之间的整数

Java将差别最大的三个优先级定义成了Thread类中的静态常量

MAX_PRIORITY:最高优先级(10)

MIN_PRIORITY:最低优先级(1)

NORM_PRIORITY:默认优先级(5)

可以通过setPriority()和getPriority()方法进行设置和获取

线程的创建和使用

在Java中一切皆对象,线程这一类事物也用了一个类来进行了描述,这个类叫做Thread类

线程的创建

1、继承Thread类

2、实现Runnable接口

1、 通过继承Thread类会出现单继承的问题,通过实现Runnable接口可以避免单继承的不足

2、 通过实现Runnable接口可以将线程的任务从线程的子类中分离出来,进行单独的封装,按照面向对象的思想将任务封装成了对象,并且可以方便实现多个线程的数据共享

1、定义一个类继承Thread,重写父类的run()方法,在run()中写上要在子线程中执行的逻辑

2、创建定义好的类,生成一个实例

3、调用这个实例的start(),启动线程(不要调用run(),这个run()是一个回调方法)

1、定义一个类实现Runnable接口,实现抽象方法run(),在run()中写上要在子线程中执行的逻辑

2、创建一个Thread实例,从构造方法参数传入1中定义类的实例

3、调用start()

Runnable方式从设计上耦合度更低,更灵活

@Override

public void run() {

int progress = 0;  //初始化为0

while(true){

System.out.println(Thread.currentThread().getName()

+"烧饭,进度"+progress+"%");

if(progress ==100){//进度到100停止循环

break;

}

try {

Thread.sleep(100);

} catch(InterruptedException e) {

// TODOAuto-generated catch block

e.printStackTrace();

}

progress++;   //每次进度+1

}

}

Threadt1 = new Thread(new CookRunnable());

t1.start();

Thread t2 = new Thread(newCookRunnable());

t2.start();

CookRunnabler=newCookRunnable();

Threadt1=newThread(r);//两个线程使用同一个Runnable对象

Threadt2=newThread(r);

//以下方式不能共享,因为是分别使用了两个Runnable对象的两个progress属性

/* Thread t1 = new Thread(newCookRunnable());

Thread t2 = new Thread(newCookRunnable());*/

t1.start();//启动

try{

Thread.sleep(50);//错开50毫秒

}catch(InterruptedExceptione) {

//TODOAuto-generated catch block

e.printStackTrace();

}

t2.start();//启动另一个线程

}

1、局部变量不能被多个线程共享

2、成员变量可以被线程共享

Thread t = new Thread(new Runnable() {

@Override

publicvoid run() {

System.out.println("开始睡眠");

try{

Thread.sleep(20000);//睡眠20秒

}catch (InterruptedException e) {

//TODO Auto-generated catch block

System.out.println("睡到一半被断了");

}

System.out.println("结束睡眠");

}

});

t.start();

try{

Thread.sleep(5000);

}catch (InterruptedException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

t.interrupt();//启动子线程5秒后打断它的睡眠

}

线程的优先级:

t2.setPriority(10);

t1.start();

t2.start();

Stop方法让线程停下:

public class CycleRunnable implements Runnable{

privateboolean control = true;

publicvoid setControl(boolean control) {

this.control= control;

}

@Override

publicvoid run() {

while(control){

try{

Thread.sleep(3000);

}catch (InterruptedException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

publicstatic void main(String[] args) {

CycleRunnabler =new CycleRunnable();

Threadt = new Thread(r);

t.setName("停不下来的线程");//设置线程名字

t.start();

Scanners = new Scanner(System.in);

while(true){

Stringline = s.nextLine();

System.out.println("line="+line);

if(line.equals("stop")){

r.setControl(false);

break;

}

}

}

礼让Yield():

Thread t2 = new Thread(new Runnable() {

@Override

publicvoid run() {

for(inti=1;i<=1000;i++){

System.out.println("      "+i);

Thread.yield();//让给别的线程使用CPU

//让当前正在执行的线程释放CPU资源,让其他线程有机会去抢占CPU资源

//有可能在释放CPU资源之后,立马自己又再抢到了CPU资源

}

}

});

Thread.currentThread()通过Thread的静态方法获得当前线程的对象,还可以调用这个对象的getName()方法获取其名字

Thread.sleep(longm)通过这个静态方法,可以睡眠m毫秒,当前线程睡眠

setName(Stringn)设置线程名

intgetPriority()获取优先级,数字越大优先级越高,优先级高则抢占CPU成功的概率高一些,优先级范围1-10,默认5

setPriority(intp)设置优先级

yield()让出CPU使用权,但可以马上再抢回来

interrupt()方法,能打断一个线程sleep()、wait()、join()等方法,能让这些方法抛出InterruptedException

join()会合,等待子线程直到它结束,加入当前正在运行的线程,等待加入的线程执行完,再继续执行被加入的线程

setDaemon(boolean)方法将指定的线程设置为后台线程,设置守护线程,所有前台线程都结束后,后台线程(守护线程)会自动结束,该方法要在start()方法之前调用

线程加入:

public class ThreadJoinDemo{

public static void main(String[] args) throwsInterruptedException {

//线程加入

ThreadJoin t1 = new ThreadJoin("线程A");

ThreadJoin t2 = new ThreadJoin("线程B");

ThreadJoin t3 = new ThreadJoin("线程C");

t1.start();

/**

* 加入线程,让指定的线程(t1)加入到当前正在运行的线程(主线程)中

* 并且保证指定的线程执行完之后,在继续执行当前线程

*/

t2.start();

t1.join();

t3.start();

}

}

class ThreadJoin extends Thread{

public ThreadJoin(String name){

super(name);

}

public void run(){

for(int i=0;i<10;i++){

try {

Thread.sleep(500);

System.out.println(Thread.currentThread().getName()+"......."+i);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

守护线程(后台线程):

public classThreadDaemonDemo {

public static void main(String[] args) throwsInterruptedException {

// 设置守护线程

ThreadDaemon t1 = new ThreadDaemon("线程A");

ThreadDaemon t2 = new ThreadDaemon("线程B");

ThreadDaemon t3 = new ThreadDaemon("线程C");

t1.start();

Thread.sleep(5000);

/*

* 设置守护线程(后台线程)

* 开启的线程默认都是前台线程,可以通过setDaemon(boolean)方法将指定线程设置为后台线程,

* 当所有前台线程都结束之后,后台线程会自动结束(无论有没有执行完)

*

* 现在,t1和主线程是前台线程,而t2和t3被设置为后台线程,也就是说当t1和主线程都结束之后,

* 也就代表前台线程全部结束了,那么两个后台线程(t2和t3)会自动结束

*/

t2.setDaemon(true);

t3.setDaemon(true);

t2.start();

t3.start();

}

}

class ThreadDaemon extendsThread {

public ThreadDaemon(String name) {

super(name);

}

@Override

public void run() {

for (int i = 1; i <= 20; i++) {

try {

Thread.sleep(500);

System.out.println(getName() +"..." +i);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

线程停止:

public class ThreadStop {

public static void main(String[] args) throwsInterruptedException {

Stops t1 = new Stops("线程A");

t1.start();

// 3秒之后停止子线程运行

Thread.sleep(3000);

// 1)使用stop方法

// t1.stop();

// 2)设置标记

// 停止线程最本质的原理其实就是让run()方法执行完

// t1.setFlag(false);

// 3)使用interrupt方法

t1.interrupt();

// System.out.println("结束线程");

}

}

class Stops extends Thread{

private boolean runFlag = true;

public Stops(String name){

super(name);

}

@Override

public void run() {

// while(flag) {

while(!isInterrupted()) { // 判断中断标记是否为true

System.out.println("子线程...");

try {

/*

* 阻塞状态会被中断标记终止,如果是被强制终止阻塞状态的话会抛出中断异常(InterruptedException)

* 并且在结束阻塞状态之后,会清除中断标记(也就是说isInterrupted()返回值为false)

*/

Thread.sleep(6000);

} catch (InterruptedException e) {

//打印异常信息

// e.printStackTrace();

break;

}

}

System.out.println("线程已经运行完毕...");

}

public  voidsetFlag(boolean flag){

this.runFlag = flag;

}

}

1.stop()方法,不建议使用,要让线程结束,就让它执行完;可以使用一个条件变量作为线程中循环条件,然后在外界通过控制这个变量,来使得线程结束(终止线程,已被废弃,不推荐使用)

2、设置标记

3.interrupt():中断线程的阻塞状态,调用该方法之后,线程会标记一个中断标记,当线程处于阻塞(比如休眠) 状态时,如果线程具备中断状态,就会直接中断当前的阻塞状态,并去除中断标记

(isInterrupted():测试线程是否已经中断)

PS:停止线程最本质的原理其实就是让run()方法执行完

生命周期:生命周期:从创建到结束的整个过程,在这期间会包含很多阶段(状态)

新建状态(New):MyThread  t1 = new MyThread();

就绪状态(Runnable):调用start()方法,使线程具有了运行资格,但是没有CPU的执行权(就绪队列:CPU在分配执行权的时候是在就绪队列中随机和挑选一个线程并分配其执行权(CPU调度)),等待CPU调度

运行状态(Running):获取了CPU的执行权,只有在运行状态下的线程才具备CPU的执行权

阻塞状态(Blocked):在运行状态下调用了sleep、wait或其他的一切方法使线程进入阻塞状态(睡眠池、等待池)

【sleep(毫秒值)《睡眠池:一块内存池,集合对象或数组》   wait()《等待池》】

《睡眠结束(时间结束或被中断)被唤醒(notify) -à>>>会再次进入就绪状态》

死亡状态(Dead):stop()    run()执行完《线程一旦结束进入死亡之后,就没有用了,该状态是不可逆的》

JAVA中CyclLink怎么用_Java多线程基本使用一相关推荐

  1. java中是否支持多重继承_java支持多重继承吗 JAVA特性面试题:

    1.简要介绍java程序的健壮性. 答:JAVA程序会在编译和运行的时候自动的检测可能出现的错误,而且它是一种强类型语言,对于类型的检查很严格,而且它的垃圾回收机制也有效的避免了内存的泄漏. 2.为什 ...

  2. java 线程的基本概念_Java多线程——多线程的基本概念和使用

    一.进程和线程的基础知识 1.进程和线程的概念 进程:运行中的应用程序称为进程,拥有系统资源(cpu.内存) 线程:进程中的一段代码,一个进程中可以有多段代码.本身不拥有资源(共享所在进程的资源) 在 ...

  3. java中访问修饰符_Java中的非访问修饰符是什么?

    java中访问修饰符 Java非访问修饰符 (Java non access modifiers) We have 7 non-access modifiers in Java. The name o ...

  4. java中审核订单流程图_Java 后端横扫阿里、滴滴、美团总结的面试经验!

    这次面试的公司有一点点多,主要是因为毕业后前两份工作找的都很草率,这次换工作就想着,emm,毕业三年了,该找个工作好好沉淀几年了. 先说下这次面试的结果吧: 到 hr 面的:阿里.美团.滴滴.金山云. ...

  5. java中常用的关键字_java中的常用的关键字

    在java编程过程中,会经常写到一些关键字,但是对于他们应用的方式其实一直是模仿状态,并没有很实质的去了解,为什么要这么用,导致程序不能优化,或者出现了bug不明所以,因而再详细的去重温了一下各种了解 ...

  6. java中怎样创建线程_java中的线程创建和使用

    Java中实现多线程有两种途径:继承Thread类或者实现Runnable接口.Runnable是接口,建议用接口的方式生成线程,因为接口可以实现多继承,况且Runnable只有一个run方法,很适合 ...

  7. java中static什么意思_java中static什么意思

    java中,static表示"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,或者进行静态导包.static的特点:1.随着类的加载而被加载:2.优先于 ...

  8. java线程看不进去_Java多线程和并发基础面试问答,看过后你不会后悔

    第一:Java多线程面试问题 1:过程和线程之间有什么不合? 一个过程是一个自力(self contained)的运行情况,它可以被看作一个法度榜样或者一个应用.而线程是在过程中履行的一个义务.Jav ...

  9. java中的vm自变量_java中JVM虚拟机内存模型详细说明

    java中JVM虚拟机内存模型详细说明 JVM的内部结构如下图: 一个优秀Java程序员,必须了解Java内存模型.GC工作原理,以及如何优化GC的性能.与GC进行有限的交互,有一些应用程序对性能要求 ...

最新文章

  1. 最长公共前缀(java实现)
  2. tensorflow的一些函数
  3. 为什么选择react?为前端开发选择React的六大理由
  4. JavaScript 虚拟键盘 A-Keyboard
  5. Android Camera架构浅析
  6. openwrt下ipk生成过程及原理
  7. Linux/Ubuntu 98版五笔安装
  8. IDEA中MyBatis使用记录
  9. python运行黑色窗口怎么弄_selenium+python 去除启动的黑色cmd窗口方法
  10. 2020年,谁还在中国卖手机?
  11. 微信发朋友圈测试用例
  12. Python中用PyPDF2拆分pdf提取页面
  13. mybatis表不存在的解决办法
  14. 计算机网络状态机,计算机网络之七:TCP协议(1)
  15. 结构化数据和非结构化数据的提取【Python篇】
  16. UVA 1646 Edge Case
  17. 7-191 百钱百鸡
  18. 【微信小程序】上传文件到阿里云OSS
  19. 51单片机GSM模块的家庭火灾报警系统设计
  20. Starday做日本跨境市场之王的决心:用品质和服务赢市场

热门文章

  1. Exchange server 2010系列教程之三 发送邮件测试
  2. grep与egrep的区别
  3. Seen.js – 使用 SVG 或者 Canvas 渲染 3D 场景
  4. 发布一个http请求封装类
  5. linux命令行快捷键
  6. 乐高ev3 读取外部数据_数据就是新乐高
  7. leetcode1237. 找出给定方程的正整数解(二分法)
  8. 如何使用Apache的Prediction IO Machine Learning Server构建推荐引擎
  9. 业精于勤荒于嬉---Go的GORM查询
  10. shell远程执行命令