此文 为垃圾文 本人复习用的 emmm
- 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程
- 并行与并发:
- 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
- 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
进程和线程的区分
第一种实现方式:通过继承Thread类来实现的 线程
摘要:
code:
package com.java.Thread; public class MyThread { public static void main(String[] args){ Apple a1 = new Apple("坏蛋"); a1.start(); Apple a2 = new Apple("好人"); a2.start(); } } class Apple extends Thread{ private String name; public Apple(String name){ this.name = name; } public void run(){ for (int i = 1; i < 10; i++){ System.out.println(name+""+i); } } }
每一个线程从的它的创建到销毁都有一个状态 如下是线程的各种状态:
线程的四种状态
然后实现现成的 第二种方式 实现 Runnable接口
code如下:
package cn.java.thread; public class RunnableDemo { public static void main(String[] args) { Test t1 = new Test("haoren"); Test t2 = new Test("hairen"); Thread th1 = new Thread(t1); Thread th2 = new Thread(t2); th1.start(); th2.start(); } } class Test implements Runnable{ private String name; public Test(String name){ this.name = name; } public void run(){ for(int i=0;i<10;i++){ System.out.println(name+":"+i); } } }
Thread和Runnable的关系
1.Thread是Ruuable的之类
2.实际上Thread和Runable的关系 跟代理设计模式很像, 这里的Thread就是代理类。我们自己所实现的类才是real。
Thread和Runnable的区别
Runable可以共享数据
code如下:
package cn.java.thread; public class ShareDemo { public static void main(String[] args) { Tickets t1 = new Tickets(); Thread th1 = new Thread(t1); Thread th2 = new Thread(t1); th1.start(); th2.start(); } } class Tickets implements Runnable{ private int ticket = 5; public void run(){ for(int i=0;i<5;i++){ if(ticket>0) System.out.print(ticket--); } } }
然后 我说说这里面的 一个叫做jojn()的东东 网上各种帖子众说纷纭 而对他的理解就是 4个字 强制执行 做一个简单的验证吧.
package com.java.Thread; public class MyJoin { public static void main(String[] ARGS){ MyThread2 mt1 = new MyThread2(); mt1.setName("线程1"); mt1.start(); for (int i = 0; i < 10; i++) { if(i==5){ try { mt1.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(i); } } } class MyThread2 extends Thread { /*public MyThread(String string) { }*/ public void run() { int i = 0; while (i < 10) { System.out.println(Thread.currentThread().getName()); i++; } } }
运行结果如下
然后在 说说 interrupt 中断 一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序。虽然初次看来它可能显得简单,但是,你必须进行一些预警以实现期望的结果。你最好还是牢记以下的几点告诫。
首先,忘掉Thread.stop方法。虽然它确实停止了一个正在运行的线程,然而,这种方法是不安全也是不受提倡的,这意味着,在未来的Java版本中,它将不复存在。
一些轻率的家伙可能被另一种方法Thread.interrupt所迷惑。尽管,其名称似乎在暗示着什么,然而,这种方法并不会中断一个正在运行的线程(待会将进一步说明),正如Listing A中描述的那样。它创建了一个线程,并且试图使用Thread.interrupt方法停止该线程。Thread.sleep()方法的调用,为线程的初始化和中止提供了充裕的时间。线程本身并不参与任何有用的操作。
code如下:
package com.java.Thread; public class MyInterrupt { public static void main(String[] args) { // TODO Auto-generated method stub MyThread3 mt = new MyThread3(); mt.start(); try { Thread.sleep(2000); System.out.println("main休眠结束"); } catch (InterruptedException e) { e.printStackTrace(); } mt.interrupt(); } } class MyThread3 extends Thread{ public void run(){ System.out.println("进入run"); try { Thread.sleep(8000); } catch (InterruptedException e) { // TODO Auto-generated catch block //e.printStackTrace(); System.out.println("run休眠结束!!!");//sleep被中断会抛出InterruptedException 推荐直接抛出 不要捕获 } System.out.println("run运行结束"); } }
然后来到线程礼让 俗话点说 就是 线程A是个君子 看见线程B是个 美女就干什么都让着她 让她先过..
code如下:
package com.java.Thread; //线程礼让 public class MyYield { public static void main(String[] ARGS){ MyThred m1 = new MyThred(); Thread t1 = new Thread(m1,"李四"); Thread t2 = new Thread(m1,"王五"); t1.start(); t2.start(); } } class MyThred implements Runnable{ @Override public void run() { for (int i = 0; i < 5; i++){ System.out.println(Thread.currentThread().getName()+"运行>>>>>" + i); if (i==2) { System.out.println("线程礼让"); Thread.currentThread().yield(); } } } }
然后 来到 setdaenmo 后台线程设置
Java中线程分为两种类型:用户线程和守护线程。通过Thread.setDaemon(false)设置为用户线程;通过Thread.setDaemon(true)设置为守护线程。如果不设置次属性,默认为用户线程。
用户线程和守护线程的区别:
1. 主线程结束后用户线程还会继续运行,JVM存活;主线程结束后守护线程和JVM的状态又下面第2条确定。
2.如果没有用户线程,都是守护线程,那么JVM结束(随之而来的是所有的一切烟消云散,包括所有的守护线程)。
code如下:
package com.java.Thread; public class SetDaemon { public static void main(String[] ARGS){ Persons p1 = new Persons(); Thread th = new Thread(p1); th.setDaemon(true);//如果不加此语句就永远无法结束 th.start(); } } class Persons implements Runnable{ @Override public void run() { while (true){ System.out.println("哈哈哈哈哈哈sss"); } } }
然后 设置线程的优先级别 这点要说说 高的不一定会优先执行.
这是定义表
通过 setPriority方法来执行
来到重点中的重点 拿个小本本记住 线程安全
导致线程安全出现的原因:
所以 我们为了解决这个问题 推出了 同步 synchronized
然后同步又有两种模式 一种是同步代码块 另外一种是同步函数 这两种同步加锁的方式不一样 = =且看我细细道来
先看看code
package cn.tread; public class TicketDemo { /** * @param args */ public static void main(String[] args) { Person2 p1 = new Person2("haoren"); Thread t1 = new Thread(p1); Thread t2 = new Thread(p1); t1.start(); t2.start(); } } class Person2 implements Runnable { private String name; private int tickets = 5; public Person2(String name) { this.name = name; } //同步代码块 需要的锁是 任意对象~ Object object1 = new Object(); public void run() { for (int i = 0; i < 5; i++) { synchronized (object1) {//object1就是传说中的锁,要同步必须使用同一个锁 if (tickets > 0) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(tickets--); } } } } }
观察上面的代码 我们 有了一个总结 同步代码的锁可以是任意对象
然后是同步的前提
同步的弊端
然后我们说说同步函数
package cn.java.thread; /* 证明同步函数用的是this这把锁 */ public class Tickets1 { /** * @param args */ public static void main(String[] args) { /* * GetTickets gt1 = new GetTickets(); GetTickets gt2 = new GetTickets(); * GetTickets gt3 = new GetTickets(); gt1.setName("窗口一"); * gt2.setName("窗口二"); gt3.setName("窗口三"); gt1.start(); gt2.start(); * gt3.start(); */ GetTickets2 gt = new GetTickets2(); Thread th1 = new Thread(gt, "窗口一"); Thread th2 = new Thread(gt, "窗口二"); Thread th3 = new Thread(gt, "窗口三"); th1.start(); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } gt.flag = true; th2.start(); th3.start(); } } class GetTickets2 implements Runnable { private int tickets = 10; boolean flag = false; Object ob = new Object(); public void run() { if (flag) { for (int i = 0; i < 10; i++) { //synchronized (ob) {//如果用ob就无法同步 synchronized (this) { if (tickets > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "卖出" + (tickets--) + "号票"+":同步代码块"); } } } } else { for (int i = 0; i < 10; i++) { function(); } } } public synchronized void function() { if (tickets > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "卖出" + (tickets--) + "号票"+":同步函数"); } } } /* * class GetTickets extends Thread{ //private static int tickets = 10; private * int tickets = 10; public void run(){ * * for (int i = 0; i < 10; i++) { if(tickets>0){ * System.out.println(Thread.currentThread().getName()+"卖出"+(tickets--)+"号票"); } * } } } */
通过 观察我们不难发现
余下的我在下一个分P写...