一、线程根底内容
1、程序、过程与线程
1、程序:Program,是一个指令的汇合
2、过程:Process,(正在执行中的程序)是一个动态的概念过程是程序的一次动态执行过程,占用特定地的地址空间
每个过程都是独立的,由3局部组成cpu,data,code
毛病:内存的节约,cpu的累赘3、线程:是过程中一个“繁多的间断管制流程”/执行门路
线程又被成为轻量级过程
Threads run at the same time,independently of one another
一个过程可领有多个并行的线程
一个过程中的线程共享雷同的内存单元/内存地址空间->能够拜访雷同的变量和对象,而且他们从同一堆中调配对象->通信、数据交换、同步操作
因为线程间的通信是在同一地址空间上进行的,所以不须要额定的通信机制,这就使得通信更简便而且信息的传递速度也更快
2、线程的创立和启动
2.1、第一种形式
继承Thread类,从新run办法,调start(启动线程),每次运行雷同的代码,进去的后果可能不一样,起因在于多线程谁先抢占资源无奈进行认为管制
package com.msbline.threadPkg;public class ThreadDemo extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++){ System.out.println(Thread.currentThread().getName() +"---"+ i); } } public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); threadDemo.start(); for (int i = 0; i < 10; i++){ System.out.println(Thread.currentThread().getName() +"==="+ i); } }}
2.2、第二种形式
实现Runnable接口,重写run办法,创立Thread对象,将刚刚创立好的Runnable的子类实现作为Thread的结构参数,通过Trhead.start()进行启动
package com.msbline.threadPkg;public class ThreadDemo02 implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++){ System.out.println(Thread.currentThread().getName() +"---"+ i); } } public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); new Thread(threadDemo).start(); for (int i = 0; i < 10; i++){ System.out.println(Thread.currentThread().getName() +"==="+ i); } }}
两种形式哪种应用更多
3、线程的生命周期
4、线程的代理设计模式
5、线程操作的相干办法
1、sleep 办法是属于 Thread 类中的,sleep 过程中线程不会开释锁,只会阻塞线程,让出cpu给其余线程,然而他的监控状态仍然放弃着,当指定的工夫到了又会主动复原运行状态,可中断,sleep 给其余线程运行机会时不思考线程的优先级,因而会给低优先级的线程以运行的机会2、yield和 sleep 一样都是 Thread 类的办法,都是暂停以后正在执行的线程对象,不会开释资源锁,和 sleep 不同的是 yield办法并不会让线程进入阻塞状态,而是让线程重回就绪状态,它只须要期待从新获取CPU执行工夫,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。还有一点和 sleep 不同的是 yield 办法只能使同优先级或更高优先级的线程有执行的机会
3、join,期待调用join办法的线程完结之后,程序再继续执行,个别用于期待异步线程执行完后果之后能力持续运行的场景。例如:主线程创立并启动了子线程,如果子线程中药进行大量耗时运算计算某个数据值,而主线程要获得这个数据值能力运行,这时就要用到 join 办法了
4、wait 办法是属于 Object 类中的,wait 过程中线程会开释对象锁,只有当其余线程调用 notify 能力唤醒此线程。wait 应用时必须先获取对象锁,即必须在 synchronized 润饰的代码块中应用,那么相应的 notify 办法同样必须在 synchronized 润饰的代码块中应用,如果没有在synchronized 润饰的代码块中应用时运行时会抛出IllegalMonitorStateException的异样
二、线程同步
1、线程同步的必要性
多个线程拜访同一个共享数据的时候,会呈现数据安全问题,比方买票,两个线程同时对一张票进行操作,可能会导致重票的问题
2、线程同步的实现
2.1、同步代码块
synchronized(共享资源,共享对象,须要是Object的子类){具体执行的代码块}
public class TicketRunnable2 implements Runnable{ private int ticket = 5; @Override public void run() { for(int i = 0; i<100; i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (this){ if(ticket > 0){ System.out.println(Thread.currentThread().getName()+"正在发售第"+(ticket--)+"票"); } } } } public static void main(String[] args) { TicketRunnable2 ticketRunnable = new TicketRunnable2(); Thread t1 = new Thread(ticketRunnable,"A"); Thread t2 = new Thread(ticketRunnable,"B"); Thread t3 = new Thread(ticketRunnable,"C"); Thread t4 = new Thread(ticketRunnable,"D"); t1.start(); t2.start(); t3.start(); t4.start(); }}
2.2、同步办法
public class TicketRunnable3 implements Runnable{ private int ticket = 5; @Override public void run() { for(int i = 0; i<100; i++){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } this.sale(); } } /** * 应用同步办法解决 */ public synchronized void sale(){ if(ticket > 0){ System.out.println(Thread.currentThread().getName()+"正在发售第"+(ticket--)+"票"); } } public static void main(String[] args) { TicketRunnable3 ticketRunnable = new TicketRunnable3(); Thread t1 = new Thread(ticketRunnable,"A"); Thread t2 = new Thread(ticketRunnable,"B"); Thread t3 = new Thread(ticketRunnable,"C"); Thread t4 = new Thread(ticketRunnable,"D"); t1.start(); t2.start(); t3.start(); t4.start(); }}
3、死锁
4、线程同步小结
三、线程间通信
1、线程间通信的必要性
一般来说,每个线程本人实现本人的工作就能够了,但有时候,线程的解决会依赖另一个线程的数据,所以就须要线程间通信,来达到同步信息的成果。
2、线程间通信的实现
参考:https://blog.csdn.net/jisuanji12306/article/details/86363390