进程是程序在处理机中的一次运行。一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不一样进程所占用的系统资源相对独立。因此进程是重量级的任务,它们之间的通讯和转换都须要操做系统付出较大的开销。java
线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程本身基本上不拥有系统资源,但它能够与同属一个进程的其余线程共享进程所拥有的所有资源。因此线程是轻量级的任务,它们之间的通讯和转换只须要较小的系统开销。编程
Java支持多线程编程,所以用Java编写的应用程序能够同时执行多个任务。Java的多线程机制使用起来很是方便,用户只需关注程序细节的实现,而不用担忧后台的多任务系统。安全
Java语言里,线程表现为线程类。Thread线程类封装了全部须要的线程操做控制。在设计程序时,必须很清晰地区分开线程对象和运行线程,能够将线程对象看做是运行线程的控制面板。在线程对象里有不少方法来控制一个线程是否运行,睡眠,挂起或中止。线程类是控制线程行为的惟一的手段。一旦一个Java程序启动后,就已经有一个线程在运行。可经过调用Thread.currentThread方法来查看当前运行的是哪个线程。网络
JAVA中建立线程能够经过继承Thread类和实现Runnable接口来建立一个线程。Runnable方式能够避免Thread 方式因为JAVA单继承特性带来的缺陷。Runnable的代码能够被多个线程(Thread实例)共享,适合于多个线程处理同一资源的状况。多线程
方式一:继承Threadide
class MyThread extends Thread{ private int ticketsCont=5; //一共有5张火车票 private String name; //窗口, 也便是线程的名字 public MyThread(String name){ this.name=name; } @Override public void run(){ while(ticketsCont>0){ ticketsCont--; //若是还有票,就卖掉一张票 System.out.println(name+"卖掉了1张票,剩余票数为:"+ticketsCont); } } } public class TicketsThread { public static void main(String args[]){ //建立三个线程,模拟三个窗口卖票 MyThread mt1=new MyThread("窗口1"); MyThread mt2=new MyThread("窗口2"); MyThread mt3=new MyThread("窗口3"); //启动三个线程,也便是窗口,开始卖票 mt1.start(); mt2.start(); mt3.start(); } }
方式二:实现Runnable接口this
class MyThread2 implements Runnable { private int ticketsCont=1000; //一共有5张火车票 @Override public void run(){ while(true){ synchronized(this){ if(ticketsCont<=0){ break; } ticketsCont--; //若是还有票,就卖掉一张票 System.out.println(Thread.currentThread().getName()+"卖掉了1张票,剩余票数为:"+ticketsCont); /*try{ Thread.sleep(50); //经过阻塞程序来查看效果 } catch(Exception e){ System.out.println(e); }*/ } } } /*@Override //不加同步锁 public void run(){ while(ticketsCont>0){ ticketsCont--; //若是还有票,就卖掉一张票 System.out.println(Thread.currentThread().getName()+"卖掉了1张票,剩余票数为:"+ticketsCont); } }*/ } public class TicketsRunnable { public static void main(String args[]){ MyThread2 mt=new MyThread2(); //建立三个线程来模拟三个售票窗口 Thread th1=new Thread(mt,"窗口1"); Thread th2=new Thread(mt,"窗口2"); Thread th3=new Thread(mt,"窗口3"); //启动三个线程,也便是三个窗口,开始卖票 th1.start(); th2.start(); th3.start(); } }
场景:一个主线程,一个守护线程,守护线程会在很长一段时间内向本地文件中写入数据,主线程进入阻塞状态等待用户的输入,一旦确认了用户的输入阻塞就会解除掉,主线程继续运行直到结束,守护线程也会随虚拟机一同结束。spa
import java.io.*; import java.util.Scanner; class Daemon implements Runnable { @Override public void run(){ System.out.println("进入守护线程"); try{ writeToFile(); } catch(Exception e){ e.printStackTrace(); } System.out.println("退出守护线程"); } private void writeToFile() throws Exception{ File filename=new File("F:/慕课网(imooc)/细说多线程之Thread VS Runnable/daemon.txt"); OutputStream os=new FileOutputStream(filename,true); int count=0; while(count<999){ os.write(("\r\nword"+count).getBytes()); System.out.println("守护线程"+Thread.currentThread().getName()+"向文件中写入word"+count++); Thread.sleep(1000); } } } public class DaemonThreadDemo { public static void main(String args[]){ System.out.println("进入主线程"+Thread.currentThread().getName()); Daemon daemonThread=new Daemon(); Thread thread =new Thread(daemonThread); thread.setDaemon(true); thread.start(); Scanner sc=new Scanner(System.in); sc.next(); System.out.println("退出主线程"+Thread.currentThread().getName()); } }
建议使用Runnable这种方式建立线程。 程序中的同一资源指的是同一个Runnable对象。安全的卖票程序中须要加入同步synchronized。操作系统