java 多线程 总结 案例
来源:互联网 发布:学java软件开发好不好 编辑:程序博客网 时间:2024/05/16 10:29
学完东西后,要学会总结,学会记录笔记,这样才会有更大的收获
首先我们了解线程和进程的基本概念
一、概念(程序 进程 线程)
1、程序:指令集 静态概念
2、进程:操作系统 调度程序 动态概念
3:线程:在进程内多条执行路径 真正的多线程是指多个cpu
二、创建
1.1 继承Thread +run()
启动:创建类对象+对象.start()
package com.org.pc;/** * 模拟龟兔赛跑 * @author lyy * 创建多线程 继承Thread 重写run(线程体) * 使用线程创建子类对象,调用对象.start() */public class Rabbit extends Thread{@Overridepublic void run() {for (int i = 0; i <100; i++) {System.out.println("兔子跑了"+ i + "步");}}public static void main(String[] args) {Thread t1 = new Rabbit();Thread t2 = new Tortoise();t1.start();t2.start();}} class Tortoise extends Thread{@Overridepublic void run() {for (int i = 0; i <100; i++) {System.out.println("乌龟跑了"+ i + "步");}}}
1.2 实现Runable+run()
启动:使用静态代理
1、创建真实角色
2、创建代理角色 Thread+引用
3、代理角色.start()
/** * 使用Runable 创建 线程 * 1、类实现Runable接口 +重写run() 真实角色类 * 2、启动多线程 使用静态代理 * 1)创建真实角色 * 2)创建代理角色+真实角色引用 * 3)调用.start() * @author lyy * */public class Programer implements Runnable{@Overridepublic void run() {for (int i = 0; i < 1000; i++) {System.out.println("一边敲代码。。。。。");}}public static void main(String[] args) {//1)创建真实角色Programer pro = new Programer();// 2)创建代理角色+真实角色引用Thread proxy = new Thread(pro);//3)调用.start()proxy.start();for (int i = 0; i < 1000; i++) {System.out.println("一边聊QQ。。。。。");}}}
1.3 实现Callable(了解)
通过Callable接口实现多线程
优点:可以获取返回值
package com.org.pc;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;/** * 使用Callable创建线程 * @author lyy * */public class Call {public static void main(String[] args) throws InterruptedException, ExecutionException {//创建线程ExecutorService ser = Executors.newFixedThreadPool(2);Race tor = new Race("千年王八",1000);Race rabbit = new Race("小兔子",500);//获取值Future<Integer> result1 = ser.submit(tor);Future<Integer> result2 = ser.submit(rabbit);Thread.sleep(2000);//休眠2秒tor.setFlag(false);//停止线程体中的循环rabbit.setFlag(false);//停止线程体中的循环int num1 = result1.get();int num2 = result2.get();System.out.println("大乌龟跑了----->"+num1+"步");System.out.println("小兔子跑了----->"+num2+"步");//停止服务ser.shutdown();}}class Race implements Callable<Integer>{private String name;//名称private long time;//延时时间private boolean flag = true;private int step = 0;//步数public Race(){}public Race(String name) {super();this.name = name;}public Race(String name, int time) {super();this.name = name;this.time = time;}@Overridepublic Integer call() throws Exception {while(flag){Thread.sleep(time);//延时step++;}return step;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getTime() {return time;}public void setTime(long time) {this.time = time;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public int getStep() {return step;}public void setStep(int step) {this.step = step;}}
新生-->就绪-->运行-->阻塞-->终止
四:线程的终止(重点)
1、自然终止:线程体正常执行完毕
2、外部干涉
1)线程类中 定义 线程体使用的标识
2)线程提供使用该标识
3) 对外提供方法改变该标识
4) 外部根据条件调用该方法
package com.org.status;public class StopDemo1 {public static void main(String[] args) {Study stu = new Study(); new Thread(stu).start(); //外部改变该标识 for (int i = 0; i < 100; i++) { if(i==50){//外部干涉 stu.stop(); }System.out.println("main......"+i);}}}class Study implements Runnable{//1)线程类中 定义 线程体使用的标识private boolean flag =true;@Overridepublic void run() {//2)线程提使用该标识while(flag){System.out.println("Study thread .....");}}//3)、对外提供方法改变该标识public void stop(){this.flag = false;}}
五:阻塞
IsAlive() 判断线程是否还活着,既线程是还未终止
getPriority()获得线程的优先级数值
setPriority() 设置线程的优先级数值
setName()给线程一个名字
getName()取得线程的名字
currentThread()取得当前正在运行的线程对象也就是取得自己本身
阻塞:join yield sleep(重点)
1、Join:合并线程
package com.org.status;/** * join:合并线程 * @author lyy * */public class JoinDemo01 extends Thread {public static void main(String[] args) throws InterruptedException {JoinDemo01 join = new JoinDemo01();Thread t = new Thread(join);//新增t.start();//就绪//cpu调度运行for (int i = 0; i < 100; i++) {if(50 == i){t.join();//main阻塞}System.out.println("main......"+i);}}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("join......"+i);}}}
2、Yield:暂停自己的线程
package com.org.status;import javax.sound.midi.Synthesizer;public class YieldDemo01 extends Thread{public static void main(String[] args) {YieldDemo01 yield = new YieldDemo01();Thread t = new Thread(yield);//新生t.start();//就绪//cpu调度运行for (int i = 0; i < 100; i++) {if(i%20 == 0){//暂停本线程mainThread.yield();}System.out.println("main......."+i);}}@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("yield......."+i);}}}
3、Sleep():休眠,不释放锁
1)、时间相关(倒计时)
package com.org.status;import java.text.SimpleDateFormat;import java.util.Date;/** * 倒计时 * 1、倒数10个数,一秒内打印一个 * 2、倒计时 * @author lyy * */public class SleepDemo01 {public static void main(String[] args) throws InterruptedException {Date endTime = new Date(System.currentTimeMillis() + 10*1000);long end = endTime.getTime();while(true){//输出System.out.println(new SimpleDateFormat("mm:ss").format(endTime));//构建下一秒的时间endTime = new Date(endTime.getTime() - 1000);//等待一秒时间Thread.sleep(1000);//如果在十秒以内继续否则退出if(end -10000 > endTime.getTime()){System.out.println("ending");break;}}}public static void test1() throws InterruptedException{int num = 10;while(true){System.out.println(num--);Thread.sleep(1000);//暂停if(num <= 0){break;}}}}
2)、模拟网络延时
package com.org.status;/** * Sleep模拟 网络延时 线程不安全的 * @author lyy * */public class SLeepDemo02 {public static void main(String[] args) {//真实角色Web12306 web = new Web12306();//代理角色Thread t1 = new Thread(web,"工程师");Thread t2 = new Thread(web,"黄牛已");Thread t3 = new Thread(web,"路人甲");//启动线程t1.start();t2.start();t3.start();}}class Web12306 implements Runnable{private int num = 80;@Overridepublic void run() {while(true){if(num <= 0){break;//跳出循环}try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}}
同步:并发多个线程访问同一份资源确保资源安全 ==> 线程安全
Synchronized --> 同步
一、同步块
Synchronized(引用类型|this|类.class){
}
package com.org.syn;public class SynDemo01 {public static void main(String[] args) {//真实角色Web123 web = new Web123();//代理角色Thread t1 = new Thread(web,"工程师");Thread t2 = new Thread(web,"黄牛已");Thread t3 = new Thread(web,"路人甲");//启动线程t1.start();t2.start();t3.start();}}class Web123 implements Runnable{private int num = 10;private boolean flag = true;@Overridepublic void run() {while(flag){test3();}}//线程不安全 锁定资源不正确public void test6(){//a b cif(num <= 0){flag =false;//跳出循环return;}synchronized (this) {try {Thread.sleep(500);//模拟 延时} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}//线程不安全 锁定资源不正确public void test5(){//a b csynchronized ((Integer)num) {if(num <= 0){flag =false;//跳出循环return;}try {Thread.sleep(500);//模拟 延时} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}//锁定范围不正确public void test4(){//a b csynchronized (this) {if(num <= 0){flag =false;//跳出循环return;}try {Thread.sleep(500);//模拟 延时} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}//线程安全,锁定正确public void test3(){//a b csynchronized (this) {if(num <= 0){flag =false;//跳出循环return;}try {Thread.sleep(500);//模拟 延时} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}public synchronized void test2(){if(num <= 0){flag =false;//跳出循环return;}try {Thread.sleep(500);//模拟 延时} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}//线程不安全public void test1(){if(num <= 0){flag =false;//跳出循环return;}try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"抢到了"+num--);}}
二、同步方法
Synchronized
线程安全的效率慢,保证资源的正确
线程不安全的效率快
三、死锁:过多的同步容易造成死锁
package com.org.syn;/** * 过多的方法可能造成死锁 * @author lyy * */public class SncDemo3 {public static void main(String[] args) {Object g = new Object();Object m = new Object();Test t1 = new Test(g,m);Test t2 = new Test(g,m);Thread proxy1 = new Thread(t1);Thread proxy2 = new Thread(t2);proxy1.start();proxy2.start();}}class Test implements Runnable{Object goods;Object money;public Test(Object goods, Object money) {this.goods = goods;this.money = money;}@Overridepublic void run() {while(true){test();}}public void test(){synchronized (goods) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}synchronized (money) {//System.out.println("一手给货");}}}class test2 implements Runnable{Object goods;Object money;public test2(Object goods, Object money) {this.goods = goods;this.money = money;}@Overridepublic void run() {while(true){test();}}public void test(){synchronized (money) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}synchronized (goods) {System.out.println("一手给货");}}}
解决方法:生产者消费者模式
先生产,在消费
package com.org.pro;/** * 一个场景,一个共同的资源 * 生产者和消费者模式信号灯法 * wait() 等待 释放锁 sleep 不释放锁 * notify()/notifyAll() 唤醒 * 与 synchronized * @author lyy * */public class Movie {private String pic;//信号灯//flag --> T 生产者生产 消费者消费 生产完成后 通知消费//flag --> f 消费者消费 生产者等待 消费完成后唤醒生产private boolean flag = true;public synchronized void play(String pic){if(!flag){//生产者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}//开始生产try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("生产了:"+pic);//生产完毕this.pic = pic;//通知消费this.notify();//生产者停下this.flag=false;}public synchronized void watch(){if(flag){//消费者等待try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}try {//开始消费Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("消费了:"+pic);//消费完毕//通知生产this.notify();//消费停止this.flag = true;}}}
package com.org.pro;/** * 生产者 * @author lyy */public class Player implements Runnable{private Movie m;public Player(Movie m) {super();this.m = m;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {if(0 == i%2){m.play("左青龙");}else{m.play("右白虎");}}}}
package com.org.pro;/** * 消费者 * @author lyy * */public class Watcher implements Runnable{private Movie m;public Watcher(Movie m) {super();this.m = m;}@Overridepublic void run() {for (int i = 0; i < 100; i++) {m.watch();}}}
package com.org.pro;public class App {public static void main(String[] args) {//共同的资源Movie m = new Movie();//多线程Player p = new Player(m);Watcher w = new Watcher(m);new Thread(p).start();new Thread(w).start();}}
新生--> start -->就绪-->运行-->阻塞-->终止
线程是一个好用但是也有点复杂的技术,博主会的也只是一点点皮毛,希望有机会能和各位多多学习!有什么不对的地方,请大家多多包涵!
想要更加熟练的运用线程还需要多多深入了解!
- java 多线程 总结 案例
- 多线程部分案例总结
- java多线程交互案例
- java多线程案例
- java多线程经典案例
- java多线程案例
- java多线程简单案例入门
- java多线程的一个案例
- 多线程 wait(),notify()方法,案例总结
- 【Java多线程】多线程案例:使用多线程向用户推送短信
- 【多线程】java多线程知识点总结
- JAVA语言基础案例总结
- 【总结】常见Java故障案例
- Java多线程之读写锁经典案例
- Java多线程生成文件性能分析案例
- Java多线程之线程分类【案例分析】
- JAVA多线程的一个简单案例
- Java多线程经典案例-生产者消费者
- 设计模式总结
- awk print与printf的差别
- url特殊字符转义及解决方法(附有例子)
- this android sdk requires ADT version 23
- Android_RecyclerView&SwipeRefreshLayout_swiperefreshlayout不显示_解决
- java 多线程 总结 案例
- 45-50K技术经理只为技能需求
- AFNetWorking实现GET、POST
- 不能将参数 1 从“const char [5]”转换为“LPCTSTR”
- NoClassDefFoundError: org/apache/ibatis/session/SqlSession
- 文件流
- studio提示非法字符:'\ufeff'
- 11g RAC 环境配置GRID时检查ASM报PRVG-10122
- 医院his系统数据库恢复