/*
多线程:进程:正在进行中的程序也就是在内存中的开辟的一块空间线程:负责程序执行的一条执行路径也可以称为执行单元一个进程至少要有一个线程也就是进程的执行实际上是线程在执行当一个程序中有多个线程的时候,这个程序就是多线程程序多线程一定能提高效率吗?不一定能提高效率,但是能合理的使用cpu资源
最关键的是能够同时执行同一个程序中的多个功能(多部分代码)JVM是不是多线程的呢?
至少会有一个线程负责程序的正常执行,执行main方法中的代码----主线程
还得有一个线程负责垃圾回收,执行finalize()方法中的代码---垃圾回收线程多线程的好处可以实现多个功能的同时执行,或相同的功能同时执行任务:进程中的每个线程执行的代码每个任务代码都有其存储位置比如:主线程的任务代码存储在main方法中垃圾回收线程的代码存储在finalize方法中执行的任务不同,任务代码的存储位置就不同线程是随着任务的存在而存在
随着任务的执行结束而从内存中消失
*/
class Test
{//重写fialize()方法,定义对象被回收的方式,该方法被垃圾回收线程执行public void finalize(){System.out.println("被回收了");}
}
class  Demo1
{public static void main(String[] args) //主线程---一个进程至少会有一个主线程{new Test();new Test();new Test();//每次运行的结果都不一样,这就是多线程的随机性,因为多个线程在抢夺cpuSystem.gc();//运行垃圾回收线程,就是把cpu让给垃圾回收线程System.out.println("Hello World!");}
}

/*
任金鹏和彭立要同时显示姓名和次数既然要同时显示,就要用多线程
如何自己创建线程?
第一种方式:
1:定义一个类继承Thread
2:重写run方法创建线程是为了执行任务,任务代码需要有存储位置run()方法就是这个存储位置
3:创建子类的实例
4:调用start()启动线程注意:主线程执行的代码在main方法中自定义线程执行的代码在run方法中run()和start的区别:
run()方法是一个普通的方法,不具备启动线程的功能,只是一个普通的方法调用
start方法可以启动线程并去执行run()中的任务代码为什么继承Thread类?public static void main(String[] args) {Thread t1 = new Thread();Thread t2 = new Thread();t1.start();t2.start();以上这段代码没有执行结果,我们创建线程是为了执行任务,任务代码需要有存储位置,run方法就是存储位置因为Thread类中的run方法没有实现任何功能,而我们创建的线程的任务代码还必须写在run方法中,所以只能是继承Thread类,并重写run方法}*/
class Test extends Thread
{private String name;public Test(String name){this.name = name;}public void run()//定义了任务{for(int i=1;i<=10;i++){//子线程的名字是  Thread-编号  编号从0开始System.out.println(Thread.currentThread().getName()+"...show..."+i);}}
}
class Demo2
{public static void main(String[] args) {Test t1 = new Test("任金鹏");//创建了一个线程Test t2 = new Test("彭立");//创建了一个线程t2.start();//启动线程t1.start();//启动线程for(int i=1;i<=10;i++){//主线程的名字是  mainSystem.out.println(Thread.currentThread().getName()+"...show..."+i);}}
}

 //线程栈中的异常:进程中的某个线程发生异常,只是该线程自己的事儿,不会影响其它线程//进程中的所有线程都执行完,进程才会结束
class Test extends Thread
{private String name;public Test(String name){this.name = name;}public void run(){int[] arr = new int[2];for(int i=1;i<=10;i++){System.out.println(arr[2]);System.out.println(Thread.currentThread().getName()+"...show..."+i);}}
}
class Demo3
{public static void main(String[] args) {Test t1 = new Test("任金鹏");Test t2 = new Test("彭立");t2.start();t1.start();// System.out.println(5/0);}
}

/*
四个窗口同时卖票
既然是同时卖票,就要用多线程
创建四个线程,每个线程都是卖票
因为都是卖票,所以四个线程执行的任务代码是相同的
只要定义一个类继承Thread类,并重写run方法就o了为了让四个线程共享100张票,需要把票修饰成static的实际使用中票不应该修饰为静态的,因为票会有很多种
那怎么解决共享100张票的问题?
创建线程的第二种方式:
1:定义一个类实现Runnable接口
2:重写接口中的run方法
3:创建该子类的实例
4:创建Thread类的实例,实际上就是在创建线程
5:把子类的实例作为参数传递给Thread类的构造方法创建线程的目的是 执行任务,而任务代码定义在实现Runnable接口的子类中所以为了让线程执行任务代码,只能是把实现了Runnable接口的子类对象作为参数传递给线程对象
6:启动线程第二种方式的特点:
1:线程任务和线程对象实现了分离,更加的面向对象
创建好了线程对象,执行什么任务不再重要,只要是实现了Runnable接口的子类对象,就可以作为参数传递给
线程对象,2:实现接口的同时还可以再继承其它类
*/
class Ticket implements Runnable//这是一个用来描述任务的类
{private  int num = 50;public void run(){while(true){if(num>0){System.out.println(Thread.currentThread().getName()+"...sale..."+num--);}}}
}
class  Demo4
{public static void main(String[] args) {//Eat  e = new Eat();Ticket t = new Ticket();Thread t0 = new Thread(e);Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);t0.start();t1.start();t2.start();t3.start();/*Ticket t0 = new Ticket();Ticket t1 = new Ticket();Ticket t2 = new Ticket();Ticket t3 = new Ticket();t0.start();t1.start();t2.start();t3.start();*/}
}
/*
为什么创建线程的第二种方式就能解决卖票问题?第一种方式创建线程类的同时还得定义任务,任务和线程是绑定在一起的,每创建一个线程都会创建一份儿资源(任务用到的数据)所以,创建四线程就创建了四份资源第二种方式:单独对任务进行描述,只需要创建一个任务对象(只有一份资源),分别让四个线程去执行为什么Thread类也实现Runnable接口?run方法是提取出的共性的方法第二种方式的关键是,线程任务和线程对象的分离建议使用第二中方式*/
class Test implements Runnable//extends Thread
{public void run(){}
}
class Demo6
{public static void main(String[] args) {Test t = new Test();Thread d = new Thread(t);}
}
/*
线程出现了线程安全问题:打印了0,-1,-2等错票
线程出现安全问题的原因:1:多个线程操作了共享数据2:操作共享数据的语句有多条,当一个线程得到cpu,执行了操作共享数据的多条代码的一部分时,还没执行完,就被其它线程抢走了cpu解决方式:当一个线程在执行操作共享数据的多条代码时,其它线程不能参与执行,只有该线程把所有操作共享数据的代码全部执行完其它线程才能参与执行解决线程安全问题的方式:同步代码块synchronized(对象)//对象是任意的{需要被同步的代码块}同步代码块的弊端:不能进入同步代码块的线程要反复的判断锁,降低性能使用同步需满足的条件:1:至少有两个或两个以上的线程2:多个线程使用同一把锁*/
class Ticket implements Runnable
{private  int num = 50;private   Object obj = new Object();public void run(){while(true){synchronized(obj){if(num>0){//线程在睡的时候不会释放锁,只是放弃了cputry{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"...sale..."+num--);}}}}
}
class  Demo6
{public static void main(String[] args) {Ticket t = new Ticket();Thread t0 = new Thread(t);Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);t0.start();t1.start();t2.start();t3.start();}
}

/*
有一个银行,可以存钱
有两个储户同时存钱,每个人存三次,每次存100*/
class Bank
{private int sum =0;private Object obj = new Object();public synchronized void add(int money)//同步函数{sum = sum +money;//---->1   ----->2System.out.println("sum="+sum);}
}
//描述任务
class Customer implements Runnable
{private Bank bank = new Bank();public void run(){for(int i=1;i<=3;i++){bank.add(100);}}
}
class Demo7
{public static void main(String[] args) {//创建任务对象Customer customer = new Customer();Thread t1 = new Thread(customer);Thread t2 = new Thread(customer);t1.start();t2.start();}
}
//同步函数的锁?锁是用来实现多个线程之间的互斥,所以同步函数也必须有锁
//同步函数使用的锁是this
/*
静态同步函数:静态进内存的时候没有使用new创建的对象,但是有其所属的类 的字节码文件对象这个对象是 Class类型的对象所以它使用的锁是 其所属的类 的字节码文件对象 类名.class*/
class Ticket implements Runnable
{private  static int num = 50;private   Object obj = new Object();boolean  flag = true;public void run(){if(flag){while(true){synchronized(Ticket.class){if(num>0){try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"...sale..."+num--);}}}}else{while(true)func();}}public static synchronized void func()//锁是Ticket.class{if(num>0){try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"...sale..."+num--);}}
}
class  Demo8
{public static void main(String[] args) {Ticket t = new Ticket();Thread t0 = new Thread(t);Thread t1 = new Thread(t);t0.start();//让主线程停一会儿,这时候活着的线程只有t0,所以t0一判断flag的值为true,就进入了同步代码块try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}//主线程睡醒后把flag的值改为false,当t1线程得到cpu的时候flag的值就是fasle了,从而执行同步函数t.flag = false;t1.start();}
}
//单例设计模式中懒汉式并发访问的问题
class Single
{private static final Single s = new Sigle();private Single(){}public static Single getInstance(){return s;}
}class Test implements Runnable
{public void run(){Single2 s = Single2.getInstance();}
}
class Single2
{private static final Single2 s = null;private Single2(){}public static Single2 getInstance(){//从第三个线程开始就不用判断锁了if(s==null){synchronized(Single2.class){if(s==null)//--->1   --->2s = new Single2();}}return s;}
}class
{public static void main(String[] args) {System.out.println("Hello World!");}
}
//死锁:
class Ticket implements Runnable
{private  static int num = 2000;private   Object obj = new Object();boolean  flag = true;public void run(){if(flag){while(true){synchronized(obj){func();}}}else{while(true)func();}}public  synchronized void func(){synchronized(obj){if(num>0){try{Thread.sleep(10);}catch(InterruptedException e){e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"...sale..."+num--);}}}
}
class  Demo10
{public static void main(String[] args) {Ticket t = new Ticket();Thread t0 = new Thread(t);Thread t1 = new Thread(t);t0.start();//让主线程停一会儿,这时候活着的线程只有t0,所以t0一判断flag的值为true,就进入了同步代码块try{Thread.sleep(20);}catch(InterruptedException e){e.printStackTrace();}//主线程睡醒后把flag的值改为false,当t1线程得到cpu的时候flag的值就是fasle了,从而执行同步函数t.flag = false;t1.start();}
}
//线程间的通信: 多个线程执行的任务不同,但是操作的资源相同//描述资源
class Resource
{String name;String sex;
}
//定义输入线程执行的任务
class Input implements Runnable
{private Resource res;private Object obj = new Object();public Input(Resource res){this.res = res;}public void run(){    int i=0;while(true){synchronized(res){if(i==0){res.name = "彭立";res.sex = "男男";}else{res.name = "徐才舒";res.sex = "女女女女女女女女女女女";}}i = (i+1)%2;//i不是共享数据}}
}//定义输出线程执行的任务
class Output implements Runnable
{private Resource res;public Output(Resource res){this.res = res;}public void run(){while(true){synchronized(res){System.out.println(res.name+"==="+res.sex);}}}
}
class  Demo11
{public static void main(String[] args) {//创建资源对象Resource res = new Resource();//创建输入线程的任务对象Input input = new Input(res);//创建输出线程的任务对象Output output = new Output(res);//创建输入线程Thread in = new Thread(input);//创建输入线程Thread out = new Thread(output);in.start();out.start();}
}
/*
一下三个方法必须用在同步中:因为同步中才有锁
wait():等待的线程会释放锁,等待的线程被放入了线程池
notify():唤醒线程池中的任意一个线程
notifyAll():唤醒线程池中的所有线程为什么wait(),notify(),notifyAll()定义在Object中?
这三个方法都要用锁,而只有同步中才有锁,而同步中的锁是任意的对象
任意对象都能调用的方法只能定义在Object中*/
class Resource
{String name;String sex;boolean flag = false;
}
//定义输入线程执行的任务
class Input implements Runnable
{private Resource res;private Object obj = new Object();public Input(Resource res){this.res = res;}public void run(){    int i=0;while(true){synchronized(res){if(res.flag)try{res.wait();}catch(InterruptedException e){e.printStackTrace();}//让持有res这个锁的线程去等待if(i==0){res.name = "彭立";res.sex = "男男";}else{res.name = "徐才舒";res.sex = "女女女女女女女女女女女";}res.flag = true;res.notify();//空唤醒}i = (i+1)%2;//i不是共享数据}}
}//定义输出线程执行的任务
class Output implements Runnable
{private Resource res;public Output(Resource res){this.res = res;}public void run(){while(true){synchronized(res){if(!res.flag)try{res.wait();}catch(InterruptedException e){e.printStackTrace();}System.out.println(res.name+"==="+res.sex);res.flag = false;res.notify();}}}
}
class  Demo12
{public static void main(String[] args) {//创建资源对象Resource res = new Resource();//创建输入线程的任务对象Input input = new Input(res);//创建输出线程的任务对象Output output = new Output(res);//创建输入线程Thread in = new Thread(input);//创建输入线程Thread out = new Thread(output);in.start();out.start();}
}

JAVA-day09-多线程相关推荐

  1. Oracle字符串转BooIean,利用Java的多线程技术实现数据库的访问.pdf

    利用Java的多线程技术实现数据库的访问.pdf 第 卷第 期 计算机应用 22 12 Voi .22 , No . 12 年 月 2002 12 Computer Appiications Dec ...

  2. Java 并发/多线程教程(四)-并发模型

    本系列译自jakob jenkov的Java并发多线程教程(本章节部分内容参考http://ifeve.com/并发编程模型),个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 并发系统可以有多 ...

  3. LeetCode1117. Building H2O --Java解法--多线程保证执行顺序--AtomicInteger

    此文首发于我的个人博客:LeetCode 1117. Building H2O --Java解法–多线程保证执行顺序–AtomicInteger - zhang0peter的个人博客 LeetCode ...

  4. Java 并发/多线程教程(五)-相同线程

    本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获.由于个人水平有限,不对之处还望矫正! 相同线程是一并发框架模型,是一个单线程系统向外扩展成多个单线程的系统.这样的结果就是 ...

  5. java 创建多线程_Java创建多线程

    Java创建多线程 下一节> 到目前为止,我们仅用到两个线程:主线程和一个子线程.然而,你的程序可以创建所需的更多线程.例如,下面的程序创建了三个子线程: // Create multiple ...

  6. Java接口多线程并发测试 (一)

    本文为作者原创,禁止转载,违者必究法律责任!!! 本文为作者原创,禁止转载,违者必究法律责任!!! Java接口多线程并发测试 一,首先写一个接口post 请求代码: import org.apach ...

  7. Java的多线程和线程池的使用,你真的清楚了吗?

    Java的多线程和线程池的使用 多线程大大提高程序运行效率,我们在开发过程中经常会开启一个线程来执行一些费时的任务.开启一个线程有4种方式,在下面的文章我将详细的去讲解. 继承Thread 继承Thr ...

  8. 《Java程序设计》实验报告——Java的多线程机制

    浙江理工大学 <Java程序设计>  实验报告  20 19-20 20学年第 1学期      学  院 信息学院 班  级 计算机科学与技术18(3) 姓  名 申屠志刚 学  号 2 ...

  9. JAVA 10(多线程)

    创建线程: 通过对java.lang包的查找,继承Thread类可以创建线程 1,建立类继承Thread类 2,复写Thread中的ran方法. 3,调用线程的start()方法,该方法的作用是,启动 ...

  10. Java中多线程的性能比较

    Java中有多种用于多线程的技术. 可以通过同步关键字,锁或原子变量来并行化Java中的一段代码. 这篇文章将比较使用synced关键字ReentrantLock,getAndIncrement()以 ...

最新文章

  1. Backup and Restore in SharePoint 2010
  2. Django的是如何工作的
  3. 公开课-C++学习路线实战导引:从0开始到操作系统内核开发
  4. springboot基本属性注入
  5. ajax request headers,ajax request VS normal request
  6. mysql分页案例_MySQL优化案例系列-mysql分页优化
  7. Python学习 之 OS模块
  8. 矩阵分析与应用(二)
  9. 简单易用的标签列表界面(宝宝用了都不哭了 )
  10. js 把含有转义符的字符串转成json格式
  11. drupal 7 ajax,【漏洞分析】CVE-2018-7600 Drupal 7.x 版本代码执行
  12. 按照斗地主的规则,完成洗牌发牌的动作。
  13. Linux基础教程: 4、用户组和用户的创建
  14. 星期零参展FHC,推出新品“Pastrami”和“微笑乐摇杯”,引爆植物肉潮流
  15. 海外几大移动游戏市场,各自有什么特点?如何选择正确的营销方式?
  16. 柯西分布——正态分布的兄弟
  17. 0101 混蛋罗心得[基本元素]
  18. 12套很酷的Google Plus图标下载
  19. 世界杯营销战,中国企业赢麻了
  20. 2022 leetcode 春季赛 LCP 53. 守护太空城

热门文章

  1. View中TouchSlop,VelocityTracker,GestureDetector
  2. 2022-03-25 redis组建哨兵及主从高可用的failover
  3. 苹果CMS10原生APP修改版 影视APP源码附安装教程
  4. Win10任务栏卡死解决方案
  5. 光格科技递交科创板上会稿:拟募资6亿 预计年营收3亿
  6. matlab绘制凸多面体,科学网—MATLAB中计算凸多边形面积和凸多面体体积的简便方法 - 王福昌的博文...
  7. 千万级中文公开免费聊天语料数据分享
  8. html5 css3时间特效,css3实现垂直时间轴特效代码
  9. ABC分析做法、步骤、Pareto图制作方法解说
  10. 淘宝店铺订单同步及获取解决方案