程序,过程,线程
- 程序:为实现特定工作,应用某种语言编写的一组指令的汇合,是一段动态的代码。
- 过程:程序的一次运行过程,或者是正在运行的一个程序。过程是资源分配的根本单位。
- 线程:线程由过程进一步细化而来,是一个程序外部的一条执行门路。线程是调度和执行的单位,每个线程领有独立的运行栈和程序计数器,线程开销很小。
Thread生命周期
Thread类中的罕用办法
- start():启动以后线程;调用以后线程的run()。
- run():通常须要重写Thread类中的此办法,将创立的线程要执行的操作申明在此办法中。
- currentThread():静态方法,返回执行以后代码的线程。
- getName():获取以后线程的名字。
- setName():设置以后线程的名字。
- yield():开释以后cpu的执行权。
- join():在线程a中调用线程b的join()办法,此时线程a就进入阻塞状态,直到线程b齐全执行完当前,线程a才完结阻塞状态。
- sleep(long millitime):让以后线程“睡眠”指定的millitime毫秒。在指定的millitime毫秒工夫内,以后线程是阻塞状态。
- isAlive():判断以后线程是否存活。
- getPriority():获取线程的优先级。
- setPriority(int p):设置线程的优先级。
- 线程的优先级有以下三种,MAX_PRIORITY:10;MIN _PRIORITY:1;NORM_PRIORITY:5。
创立多线程的形式
继承Thread类
步骤:
- 创立一个继承于Thread类的子类;
- 重写Thread类中的run()办法,将次线程执行的操作申明在run()办法中。
- 创立Thread类的子类对象。
- 通过此对象调用start()。
举例:三个窗口进行卖票(存在线程平安问题)
class MThread extends Thread{ private static int tickets = 100; @Override public void run() { while(true){ if(tickets > 0){ System.out.println(getName() + "卖票,票号为:" + tickets--); }else{ break; } } }}public class ThreadTest { public static void main(String[] args) { MThread t1 = new MThread (); MThread t2 = new MThread (); MThread t3 = new MThread (); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}
阐明:局限于类的单继承性。
实现Runnable接口
步骤:
- 创立一个实现Runnable接口的类。
- 实现类去实现Runnable中的形象办法:run()。
- 创立实现类的对象。
- 将此对象作为参数传递到Thread类的结构器中,创立Thread类的对象。
- 通过Thread类的对象调用start()。
举例:三个窗口进行卖票(存在线程平安问题)
class MThread implements Runnable{ private int tickets = 100; @Override public void run() { while(true){ if(tickets > 0){ System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + tickets--); }else{ break; } } }}public class ThreadTest { public static void main(String[] args) { MThread m = new MThread(); Thread t1 = new Thread(m); Thread t2 = new Thread(m); Thread t3 = new Thread(m); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}
阐明:不会局限于类的单继承性;适宜解决多个线程共享数据的状况。
实现Callable接口
步骤:
- 创立一个实现Callable的实现类。
- 实现call办法,将此线程须要执行的操作申明在call()中。
- 创立Callable接口实现类的对象。
- 将此Callable接口实现类的对象作为参数传递到FutureTask结构器中,创立FutureTask的对象。
- 将FutureTask的对象作为参数传递到Thread类的结构器中,创立Thread对象,并调用start()。
举例:遍历100以内的偶数,并且计算他们的和
class MThread implements Callable{ @Override public Object call() throws Exception { int sum = 0; for (int i = 2; i < 101; i+=2) { System.out.println(i); sum += i; } } return sum; }}public class ThreadTest { public static void main(String[] args) { MThread thread = new MThread (); FutureTask futureTask = new FutureTask(thread); new Thread(futureTask).start(); try { //get()返回值即为FutureTask结构器参数Callable实现类重写的call()的返回值。 Object sum = futureTask.get(); System.out.println("总和为:" + sum); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }}
阐明:call()办法有返回值,并且能够抛出异样;callable反对泛型。
线程池
步骤:
- 提供指定线程数量的线程池。
- 执行指定的线程的操作。须要提供实现Runnable接口或Callable接口实现类的对象。
- 敞开线程池。
举例:两个线程遍历100以内的奇偶数
class NumberThread implements Runnable{ @Override public void run() { for(int i = 1;i < 101; i+=2){ System.out.println(Thread.currentThread().getName() + ": " + i); } }}class NumberThread1 implements Runnable{ @Override public void run() { for(int i = 2;i < 101; i+=2){ System.out.println(Thread.currentThread().getName() + ": " + i); } }}public class ThreadPool { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(10); ThreadPoolExecutor service1 = (ThreadPoolExecutor) service; service.execute(new NumberThread());//实用于Runnable service.execute(new NumberThread1());//实用于Runnable //service.submit(Callable callable);//应用于Callable service.shutdown(); }}
阐明:进步了响应速度;升高资源耗费;便于线程治理。
线程同步机制
解决线程平安问题
同步代码块
synchronized(对象){//须要被同步的代码}
举例:三个窗口卖票
class Windows extends Thread{ private static int tickets = 100; @Override public void run() { while(true){ synchronized(Windows.class){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if(tickets > 0){ System.out.println(getName() + "卖票,票号为:" + tickets--); }else{ break; } } } }}public class Test { public static void main(String[] args) { Windows t1 = new Windows(); Windows t2 = new Windows(); Windows t3 = new Windows(); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start(); t2.start(); t3.start(); }}
同步办法
将synchronized放到办法的申明中。
举例:三个窗口卖票。
class Windows implements Runnable { private int tickets = 100; @Override public void run() { while(true){ show(); } } private synchronized void show(){ if(tickets > 0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + tickets--); } }}public class Test{ public static void main(String[] args) { Windows t = new Windows(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); t1.setName("窗口1"); t2.setName("窗口2"); t3.setName("窗口3"); t1.start();t2.start();t3.start(); }}
Lock
class A{ private final ReentrantLock lock = new ReentrantLock(); public void m(){ lock.lock(); try{ //保障线程平安的代码 } finally{ lock.unlock(); } }}
举例:三个窗口卖票
class Window implements Runnable{ private int ticket = 100; private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while(true){ try{ lock.lock(); if(ticket > 0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket--); } }finally { lock.unlock(); } } }}public class LockTest { public static void main(String[] args) { Window w = new Window(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.setName("线程1");t2.setName("线程2");t3.setName("线程3"); t1.start();t2.start();t3.start(); }}
synchronized和lock比照:
- lock是显示锁,手动开启和敞开;synchronized是隐式锁,出了作用域主动开释。
- lock只有代码块锁;synchronized有代码块锁和办法锁。
- 应用lock锁,JVM将破费较少的工夫来调度线程,性能更好;并且具备更好的扩展性。
线程通信
三个办法
- wait():一旦执行此办法,以后线程就进入阻塞状态,并开释同步监视器。
- )notify():一旦执行此办法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
- notifyAll():一旦执行此办法,就会唤醒所有被wait的线程。
阐明
- wait(),notify(),notifyAll()三个办法必须应用在同步代码块或同步办法中。
- wait(),notify(),notifyAll()三个办法的调用者必须是同步代码块或同步办法中的同步监视器。否则,会呈现IllegalMonitorStateException异样。
- wait(),notify(),notifyAll()三个办法是定义在java.lang.Object类中。
举例:生产者消费者问题
class Clerk{ private int productCount = 0; public synchronized void produceProduct(){ if(productCount < 20){ productCount ++; System.out.println(Thread.currentThread().getName() + "生产第" + productCount + "个产品"); notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void consumeProduct() { if(productCount > 0){ System.out.println(Thread.currentThread().getName() + "生产第" + productCount + "个产品"); productCount --; notify(); }else { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }}class Productor extends Thread{ private Clerk clerk; public Productor(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println("生产者" + Thread.currentThread().getName() + "开始生产"); while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk.produceProduct(); } }}class Consumer extends Thread{ private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println("消费者" + Thread.currentThread().getName() + "取走产品"); while(true){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } clerk.consumeProduct(); } }}public class ProductTest { public static void main(String[] args) { Clerk clerk = new Clerk(); Productor p1 = new Productor(clerk); p1.setName("生产者1"); Consumer c1 = new Consumer(clerk); c1.setName("消费者1"); p1.start();c1.start(); }}
最初
在文章的最初作者为大家整顿了很多材料!包含java外围知识点+全套架构师学习材料和视频+一线大厂面试宝典+面试简历模板+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书等等!
全副收费分享给大家,欢送关注公众号:前程有光支付!