进程:
是指一个内存中的应用程序,每个进程都有一个独立的内存空间。线程:
是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行。一个进程至少有一个线程。线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分为若干的线程同步:排队执行,效率低但安全。 异步:同步执行,效率高但数据不安全。 并发:指两个或多个事件在同一个时间段内发生。 并行:指两个或多个事件在同一个时刻发生(同时发生)
实现多线程的一种方式 实例:
public class Demo4 { public static void main(String[] args) { //Thread MyThread m = new MyThread(); m.start(); for (int i=0;i<10;i++){ System.out.println("汗滴禾下土"+i); } } } class MyThread extends Thread{ /** * run方法就是线程要执行的人物方法 */ @Override public void run() { //这里的代码就是一条新的执行路径。 //这个执行路径的触发方式,不是调用run方法,而是通过Thread对象的start()来启动任务 for (int i=0;i<10;i++){ System.out.println("锄禾日当午"+i); } } }两条线程所执行的时序图:
#mermaid-svg-gUXJ8HIU25bTuRza .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-gUXJ8HIU25bTuRza .label text{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .node rect,#mermaid-svg-gUXJ8HIU25bTuRza .node circle,#mermaid-svg-gUXJ8HIU25bTuRza .node ellipse,#mermaid-svg-gUXJ8HIU25bTuRza .node polygon,#mermaid-svg-gUXJ8HIU25bTuRza .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-gUXJ8HIU25bTuRza .node .label{text-align:center;fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .node.clickable{cursor:pointer}#mermaid-svg-gUXJ8HIU25bTuRza .arrowheadPath{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-gUXJ8HIU25bTuRza .flowchart-link{stroke:#333;fill:none}#mermaid-svg-gUXJ8HIU25bTuRza .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-gUXJ8HIU25bTuRza .edgeLabel rect{opacity:0.9}#mermaid-svg-gUXJ8HIU25bTuRza .edgeLabel span{color:#333}#mermaid-svg-gUXJ8HIU25bTuRza .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-gUXJ8HIU25bTuRza .cluster text{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-gUXJ8HIU25bTuRza .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-gUXJ8HIU25bTuRza text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-gUXJ8HIU25bTuRza .actor-line{stroke:grey}#mermaid-svg-gUXJ8HIU25bTuRza .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-gUXJ8HIU25bTuRza .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-gUXJ8HIU25bTuRza #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-gUXJ8HIU25bTuRza .sequenceNumber{fill:#fff}#mermaid-svg-gUXJ8HIU25bTuRza #sequencenumber{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza #crosshead path{fill:#333;stroke:#333}#mermaid-svg-gUXJ8HIU25bTuRza .messageText{fill:#333;stroke:#333}#mermaid-svg-gUXJ8HIU25bTuRza .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-gUXJ8HIU25bTuRza .labelText,#mermaid-svg-gUXJ8HIU25bTuRza .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-gUXJ8HIU25bTuRza .loopText,#mermaid-svg-gUXJ8HIU25bTuRza .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-gUXJ8HIU25bTuRza .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-gUXJ8HIU25bTuRza .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-gUXJ8HIU25bTuRza .noteText,#mermaid-svg-gUXJ8HIU25bTuRza .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-gUXJ8HIU25bTuRza .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-gUXJ8HIU25bTuRza .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-gUXJ8HIU25bTuRza .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-gUXJ8HIU25bTuRza .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .section{stroke:none;opacity:0.2}#mermaid-svg-gUXJ8HIU25bTuRza .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-gUXJ8HIU25bTuRza .section2{fill:#fff400}#mermaid-svg-gUXJ8HIU25bTuRza .section1,#mermaid-svg-gUXJ8HIU25bTuRza .section3{fill:#fff;opacity:0.2}#mermaid-svg-gUXJ8HIU25bTuRza .sectionTitle0{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .sectionTitle1{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .sectionTitle2{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .sectionTitle3{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-gUXJ8HIU25bTuRza .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .grid path{stroke-width:0}#mermaid-svg-gUXJ8HIU25bTuRza .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-gUXJ8HIU25bTuRza .task{stroke-width:2}#mermaid-svg-gUXJ8HIU25bTuRza .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .taskText:not([font-size]){font-size:11px}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-gUXJ8HIU25bTuRza .task.clickable{cursor:pointer}#mermaid-svg-gUXJ8HIU25bTuRza .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-gUXJ8HIU25bTuRza .taskText0,#mermaid-svg-gUXJ8HIU25bTuRza .taskText1,#mermaid-svg-gUXJ8HIU25bTuRza .taskText2,#mermaid-svg-gUXJ8HIU25bTuRza .taskText3{fill:#fff}#mermaid-svg-gUXJ8HIU25bTuRza .task0,#mermaid-svg-gUXJ8HIU25bTuRza .task1,#mermaid-svg-gUXJ8HIU25bTuRza .task2,#mermaid-svg-gUXJ8HIU25bTuRza .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutside0,#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutside2{fill:#000}#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutside1,#mermaid-svg-gUXJ8HIU25bTuRza .taskTextOutside3{fill:#000}#mermaid-svg-gUXJ8HIU25bTuRza .active0,#mermaid-svg-gUXJ8HIU25bTuRza .active1,#mermaid-svg-gUXJ8HIU25bTuRza .active2,#mermaid-svg-gUXJ8HIU25bTuRza .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-gUXJ8HIU25bTuRza .activeText0,#mermaid-svg-gUXJ8HIU25bTuRza .activeText1,#mermaid-svg-gUXJ8HIU25bTuRza .activeText2,#mermaid-svg-gUXJ8HIU25bTuRza .activeText3{fill:#000 !important}#mermaid-svg-gUXJ8HIU25bTuRza .done0,#mermaid-svg-gUXJ8HIU25bTuRza .done1,#mermaid-svg-gUXJ8HIU25bTuRza .done2,#mermaid-svg-gUXJ8HIU25bTuRza .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-gUXJ8HIU25bTuRza .doneText0,#mermaid-svg-gUXJ8HIU25bTuRza .doneText1,#mermaid-svg-gUXJ8HIU25bTuRza .doneText2,#mermaid-svg-gUXJ8HIU25bTuRza .doneText3{fill:#000 !important}#mermaid-svg-gUXJ8HIU25bTuRza .crit0,#mermaid-svg-gUXJ8HIU25bTuRza .crit1,#mermaid-svg-gUXJ8HIU25bTuRza .crit2,#mermaid-svg-gUXJ8HIU25bTuRza .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-gUXJ8HIU25bTuRza .activeCrit0,#mermaid-svg-gUXJ8HIU25bTuRza .activeCrit1,#mermaid-svg-gUXJ8HIU25bTuRza .activeCrit2,#mermaid-svg-gUXJ8HIU25bTuRza .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-gUXJ8HIU25bTuRza .doneCrit0,#mermaid-svg-gUXJ8HIU25bTuRza .doneCrit1,#mermaid-svg-gUXJ8HIU25bTuRza .doneCrit2,#mermaid-svg-gUXJ8HIU25bTuRza .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-gUXJ8HIU25bTuRza .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-gUXJ8HIU25bTuRza .milestoneText{font-style:italic}#mermaid-svg-gUXJ8HIU25bTuRza .doneCritText0,#mermaid-svg-gUXJ8HIU25bTuRza .doneCritText1,#mermaid-svg-gUXJ8HIU25bTuRza .doneCritText2,#mermaid-svg-gUXJ8HIU25bTuRza .doneCritText3{fill:#000 !important}#mermaid-svg-gUXJ8HIU25bTuRza .activeCritText0,#mermaid-svg-gUXJ8HIU25bTuRza .activeCritText1,#mermaid-svg-gUXJ8HIU25bTuRza .activeCritText2,#mermaid-svg-gUXJ8HIU25bTuRza .activeCritText3{fill:#000 !important}#mermaid-svg-gUXJ8HIU25bTuRza .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-gUXJ8HIU25bTuRza g.classGroup text .title{font-weight:bolder}#mermaid-svg-gUXJ8HIU25bTuRza g.clickable{cursor:pointer}#mermaid-svg-gUXJ8HIU25bTuRza g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-gUXJ8HIU25bTuRza g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-gUXJ8HIU25bTuRza .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-gUXJ8HIU25bTuRza .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-gUXJ8HIU25bTuRza .dashed-line{stroke-dasharray:3}#mermaid-svg-gUXJ8HIU25bTuRza #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza .commit-id,#mermaid-svg-gUXJ8HIU25bTuRza .commit-msg,#mermaid-svg-gUXJ8HIU25bTuRza .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-gUXJ8HIU25bTuRza g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-gUXJ8HIU25bTuRza g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-gUXJ8HIU25bTuRza g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-gUXJ8HIU25bTuRza .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-gUXJ8HIU25bTuRza .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-gUXJ8HIU25bTuRza .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-gUXJ8HIU25bTuRza .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-gUXJ8HIU25bTuRza .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-gUXJ8HIU25bTuRza .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-gUXJ8HIU25bTuRza .edgeLabel text{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-gUXJ8HIU25bTuRza .node circle.state-start{fill:black;stroke:black}#mermaid-svg-gUXJ8HIU25bTuRza .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-gUXJ8HIU25bTuRza #statediagram-barbEnd{fill:#9370db}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-state .divider{stroke:#9370db}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-gUXJ8HIU25bTuRza .note-edge{stroke-dasharray:5}#mermaid-svg-gUXJ8HIU25bTuRza .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-gUXJ8HIU25bTuRza .error-icon{fill:#522}#mermaid-svg-gUXJ8HIU25bTuRza .error-text{fill:#522;stroke:#522}#mermaid-svg-gUXJ8HIU25bTuRza .edge-thickness-normal{stroke-width:2px}#mermaid-svg-gUXJ8HIU25bTuRza .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-gUXJ8HIU25bTuRza .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-gUXJ8HIU25bTuRza .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-gUXJ8HIU25bTuRza .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-gUXJ8HIU25bTuRza .marker{fill:#333}#mermaid-svg-gUXJ8HIU25bTuRza .marker.cross{stroke:#333} :root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-gUXJ8HIU25bTuRza { color: rgba(0, 0, 0, 0.75); font: ; } 程序启动 main线程开启 main线程执行 创建m对象 循环10次 程序结束 m线程开启 循环10次第二种实现多线程的方法 实例:
public class Demo5 { public static void main(String[] args) { MyRunnable m = new MyRunnable(); Thread t = new Thread(m); t.start(); for (int i=0;i<5;i++){ System.out.println("汗滴禾下土"+i); } } } class MyRunnable implements Runnable{ @Override public void run() { for (int i=0;i<5;i++){ System.out.println("锄禾日当午"+i); } } }实现Runnable接口与继承Thread相比有如下优势:
通过创建任务,然后给线程分配的方式来实现多线程,更适合多个线程执行相同的任务。可以避免单继承所带来的局限性。任务与线程本身是分离的,提高了程序的健壮性。后续学习的线程池技术,接收Runnable类型的任务,不接受Thread类型的任务。Thread也有优势比如可以很简单的实现方式,通过匿名内部类的方法开启一个线程。 例:
public class Demo5 { public static void main(String[] args) { //匿名内部类方法开启新的线程 new Thread(){ @Override public void run() { for (int i=0;i<5;i++){ System.out.println("锄禾日当午"+i); } } }.start(); for (int i=0;i<5;i++){ System.out.println("汗滴禾下土"+i); } } }常用构造方法:
构造器描述Thread()分配新的 Thread对象。Thread(Runnable target)分配新的 Thread对象。Thread(Runnable target, String name)分配新的 Thread对象。Thread(String name)分配新的 Thread对象。常用的方法:
变量和类型方法描述longgetId()返回此Thread的标识符。StringgetName()返回此线程的名称。intgetPriority()返回此线程的优先级。voidsetPriority(int newPriority)更改此线程的优先级。static ThreadcurrentThread()返回对当前正在执行的线程对象的引用。voidstart()导致此线程开始执行; Java虚拟机调用此线程的run方法。static voidsleep(long millis)导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。static voidsleep(long millis, int nanos)导致当前正在执行的线程休眠(暂时停止执行)指定的毫秒数加上指定的纳秒数,具体取决于系统定时器和调度程序的精度和准确性。voidsetDaemon(boolean on)将此线程标记为 daemon线程或用户线程。daemon(守护线程)是依附于用户线程的。
面试题: 如何将一个线程停止: 不能使用stop()方法,因为stop()方法极有可能导致操作在没有执行完的时候就被终止导致资源没有被释放,从而占用资源。 正确的方法是使用标记的方法,在线程执行过程中不断观察,一旦标记改变,return返回run方法就可以了。
简单的可以理解为所有需要消耗时间的操作。例:文件读取,接受用户输入
概述: 一个线程是一个独立的执行路径,他是否应该结束,应该由其自身决定。
使用interrupt()方法进行中断操作。
用于守护用户线程。 用户线程:当一个进程不包含任何存活的用户线程时,进程结束。 守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动结束。 如何设置:
//只需要在线程开始前将其设置为守护线程即可。 Thread t1 = new Thread(new MyRunnable()); //这样就将t1设置为了守护线程。 t1.setDaemon(true);线程不安全 案例:
public static void main(String[] args){ Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{ private int count = 10; @Override public void run() { while(count>0){ System.out.println("正在准备卖票"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println("出票成功,剩余票数为:"+count); } } }卖票(因为多个线程去争抢同一个数据count),所以有可能出现count=-1或者-2的情况,因为一旦在还没减到0的时候其他的线程也可能会抢到时间片导致线程并没有结束,所以并不安全。
**线程不安全解决方案1:**同代码块
**格式:**synchronized(锁对象){}
注:每一个线程要看同一把锁,这样才有会实现线程安全,如果每个人都看自己的锁,那是没有意义的。
例:
public static void main(String[] args){ Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{ private int count = 10; //对象要new在run()的外部,这样可以保证三个线程看的是同把锁,如果new在run()中,那每个线程在调用run()的时候都会自己生成一把锁,这样同步代码块就失去了意义。 private Object o = new Object(); @Override public void run() { while(true){ //在while循环里保证将卖票这个操作上锁 synchronized (o){ if (count>0){ System.out.println("正在准备卖票"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+"出票成功,剩余票数为:"+count); } } } } }**线程不安全解决方案2:**同代方法 用方法来实现 例:
public static void main(String[] args){ Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{ private int count = 10; @Override public void run() { while(true){ boolean flag = sale(); if (!flag){ break; } } } public synchronized boolean sale(){ if (count>0){ System.out.println("正在准备卖票"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+"出票成功,剩余票数为:"+count); return true; } return false; } }**注:**如果一个类中有很多个同步方法,那么他们用的锁都是同一个this,当其中一个方法执行,其他的方法也需要等待。
**线程不安全解决方案3:**显示锁Lock 例:
public static void main(String[] args){ Runnable run = new Ticket(); new Thread(run).start(); new Thread(run).start(); new Thread(run).start(); } static class Ticket implements Runnable{ //票数 private int count = 10; //显示锁 private Lock l = new ReentrantLock(); @Override public void run() { while(true){ l.lock(); if (count>0){ System.out.println("正在准备卖票"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+"出票成功,剩余票数为:"+count); }else { break; } l.unlock(); } } }java中默认的都是不公平的锁(同步代码块、同步方法、显示锁)。 Lock实现公平锁,显示锁的构造方法可以传入一个布尔类型的值默认为false,设置为true则将Lock更改为公平锁。
案例:
public static void main(String[] args) { Culprit c = new Culprit(); Police p = new Police(); new MyThread(c,p).start(); c.say(p); } static class MyThread extends Thread{ private Culprit c; private Police p; public MyThread(Culprit c, Police p) { this.c = c; this.p = p; } @Override public void run() { p.say(c); } } static class Culprit{ public synchronized void say(Police p){ System.out.println("罪犯:你放了我,我放了人质"); p.fun(); } public synchronized void fun(){ System.out.println("罪犯被放了,警察也救到了人质"); } } static class Police{ public synchronized void say(Culprit c){ System.out.println("警察:你放了人质,我放过你"); c.fun(); } public synchronized void fun(){ System.out.println("警察就到了人质,罪犯被放走了"); } }NEW:尚未启动的线程处于此状态。 RUNNABLE:在Java虚拟机中执行的线程处于此状态。 BLOCKED:被阻塞等待监视器锁定的线程处于此状态。 WAITING:无限期等待另一个线程执行特定操作的线程处于此状态。 TIMED_WAITING:正在等待另一个线程执行最多指定等待时间的操作的线程处于此状态。 TERMINATED:已退出的线程处于此状态
相同点:都是接口、都可以编写多线程程序、都采用Thread.start()启动线程。 不同点: 1.Runnable没有返回值,Callable可以返回执行结果。 2.Callable的cal()允许抛出异常,Runnable的run()不能抛出异常。 获取返回值:Callalble接口支持返回执行结果,需要调用FutureTask.get()得到,此方法会阻塞主进程的继续往下执 行,如果不调用不会阻塞。
如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程 就会大大降低 系统的效率,因为频繁创建线程和销毁线程需要时间. 线程池就是一个容纳多个线程的容 器,池中的线程可以反复使用,省去了频繁创建线程对象的操作,节省了大量的时间和资源。
线程池的优点:
降低资源消耗提高响应速度提高线程的可管理性例:
public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); service.execute(new Runnable() { @Override public void run() { System.out.println("线程的名称:"+Thread.currentThread().getName()); } }); service.execute(new Runnable() { @Override public void run() { System.out.println("线程的名称:"+Thread.currentThread().getName()); } }); service.execute(new Runnable() { @Override public void run() { System.out.println("线程的名称:"+Thread.currentThread().getName()); } }); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } service.execute(new Runnable() { @Override public void run() { System.out.println("线程的名称:"+Thread.currentThread().getName()); } }); }public static void main(String[] args) { ScheduledExecutorService service = Executors.newScheduledThreadPool(2); service.schedule(new Runnable() { @Override public void run() { System.out.println(“线程名称:”+Thread.currentThread().getName()); } },5,TimeUnit.SECONDS); service.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(“线程名称:”+Thread.currentThread().getName()); } },3,1, TimeUnit.SECONDS); }
函数式编程思想。 注:想要实现Lambda表达式的接口必须只有一个静态方法。因为Lambda表达式是为了实现这个方法所以才可以替换为一个函数表达式 例:
public static void main(String[] args) { print((int x, int y) -> { return x+y; },100,200); } public static void print(MyMath m,int x,int y){ int num = m.sum(x,y); System.out.println(num); } static interface MyMath{ int sum(int x,int y); }