进程: 进程是一个具备必定独立功能的程序关于某个数据集合的一次运行活动,它是系统进行资源分配和调度的一个独立单位。html
线程: 线程是进程的一个实体,是CPU调度和分配的基本单位。线程基本不拥有系统资源,与同一个进程的其余线程共享进程中所拥有的全部资源。java
应用程序必须运行完全部的前台线程才能够退出;而对于后台线程,应用程序则能够不考虑其是否已经运行完毕而直接退出,全部的后台线程在应用程序退出时都会自动结束。面试
第一种方式:直接继承线程Thread类建立对象
1.Thread子类没法再从其它类继承(java语言单继承)。
2.编写简单,run()方法的当前对象就是线程对象,可直接操做。c#
public MyThread extends Thread{ …… public void run() { 线程体逻辑 } } //建立及启动线程: MyThread t = new MyThread(); t.start();
第二种方式:使用Runnable接口建立线程
1.能够实现多个线程资源共享
2.线程体run()方法所在的类能够从其它类中继承一些有用的属性和方法api
public MyThread implements Runnable { …… public void run() { 线程体逻辑 } } //建立及启动线程: MyThread t = new MyThread(); Thread t1 = new Thread(t); t1.start();
线程安全:线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其余线程不能进行访问直到该线程读取完,其余线程才可以使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程前后更改数据形成所获得的数据是脏数据。
缘由是因为不一样线程获取到资源时进行运算,但将来得及写入时,线程改变,则另外线程读入的资源就是错误,致使全部线程写入读入不一样步。
解决办法:缓存
线程同步通讯是但愿实现两个或多个线程之间的某种制约关系
实现:首先是用监视器synchronized来保证每次只有一个线程调用方法,其次引入一个boolean型标志来判断该线程是否执行或wait,两个线程时使用notify(),多个线程时用notifyAll()来让出监视器并唤醒其余线程。这样就实现了线程之间的关系。安全
//使用wait和notifyAll实现线程间同步通讯 (两个存钱线程,一个取钱线程) class Account{ volatile private int value; //布尔标志 volatile private boolean isMoney = false; //put设为同步方法 synchronized void put(int i) { while(isMoney){ try{ wait();} //线程等待 catch(){Exception e}{} } value = value + i; System.out.println("存入"+i+" 帐上金额为:"+value); isMoney = true;//设置标志 notifyAll(); //唤醒等待资源的全部线程 } synchronized int get(int i) {//同步方法 while(!isMoney) ){ try { wait();} catch(){Exception e}{} } if (value>i) value = value - i; else { i = value; value = 0; } System.out.println("取走"+i+" 帐上金额为:"+value); isMoney = false; notifyAll(); return i; } } class Save implements Runnable{ private Account a1; public Save(Account a1){this.a1 = a1;} public void run(){ while(true){ a1.put(100);} } } class Fetch implements Runnable { private Account a1; public Fetch(Account a1) { this.a1 = a1 ;} public void run(){ while(true){ a1.get(100);} } } public class TestCommunicate{ public static void main(String[] args){ Account a1 = new Account(); new Thread(new Save(a1)).start(); new Thread(new Save(a1)).start(); new Thread(new Fetch(a1)).start(); }}
若是多个线程都处于等待状态,彼此须要对方所占用的监视器全部权,多线程
就构成死锁(deadlock),Java即不能发现死锁也不能避免死锁。ide
方法一:{ synchronized(A) { …. synchronized(B) { …. } } } 方法二:{ synchronized(B) { …. synchronized(A) { …. } } }
注意函数
可能发生死锁的代码执行中不必定会死锁,由于线程之间的执行存
在很大的随机性。
线程方法suspend()、resume()、stop()因为存在引发死锁的可能,
于是逐渐不用(Deprecated)。
class Account { volatile private int value; void put(int i) { synchronized(this) { value = value + i; System.out.println("存入"+i+" 帐上金额为:"+value); } } synchronized int get(int i) { if (value>i) value = value - i; else { i = value; value = 0; } System.out.println("取走"+i+" 帐上金额为:"+value); return i; } } class Save implements Runnable { int a=2000; private Account a1; public Save(Account a1) { this.a1 = a1; } public void run() { while(a-->0){ a1.put(100); } } } class Fetch implements Runnable { int a=2000; private Account a1; public Fetch(Account a1) {this.a1 = a1 ;} public void run() { while(a-->0){ a1.get(100); } } } public class Test{ public static void main(String[] args){ Account a1 = new Account(); new Thread(new Save(a1)).start(); new Thread(new Fetch(a1)).start(); } }
put方法的代码块被监视,get函数被监视,保证了value的正确性,输出结果为存钱取钱的随机顺序, 这里没有设置存取的制约关系。
public class test {//如何中断线程?答案是添加一个开关。 private volatile static boolean on = false; //内部类 public class MyThreadTwo implements Runnable { @Override public void run() { try { System.out.println("into ---" + Thread.currentThread().getName()); Thread.sleep(10000);//因为等待时间10秒,输出多,上面的into语句被覆盖了 System.out.println("out " + Thread.currentThread().getName()); test.on=true; } catch (InterruptedException e) { e.printStackTrace(); } } } private void start() { //一个Thread的构造函数接受一个Runnable参数,而传入的lambda表达式正好符合其run()函数, // 因此Java编译器推断它为Runnable。 Thread thread1 = new Thread(() -> { while (!on) { System.out.println(Thread.currentThread().getName()); } }); Thread thread2 = new Thread(new MyThreadTwo()); thread1.start(); thread2.start(); } public static void main(String[] args) { test test = new test(); test.start(); } }
class Cache { volatile private int value; final private int productSize; public Cache(int pro) { productSize = pro; } synchronized void put() {//存 while (value == productSize) {//缓存区产品长度满时等待,不存 try { wait();//线程等待 } catch (InterruptedException e) { e.printStackTrace(); } } value = value + 1; System.out.println(Thread.currentThread().getName() + "存了" + 1+", 现value=" + value); notifyAll();//唤醒等待资源的全部线程 } synchronized void get() {//取 while (value == 0) {//缓存区产品长度空时等待,不取 try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } value = value - 1; System.out.println(Thread.currentThread().getName() + "取了" + 1+", 现value=" + value); notifyAll(); } } //生产者 class produce implements Runnable { private Cache a1; public produce(Cache a1) { this.a1 = a1; } public void run() { while (true) { a1.put(); } } } //消费者 class consumer implements Runnable { private Cache a1; public consumer(Cache a1) { this.a1 = a1; } public void run() { while (true) { a1.get(); } } } public class test{ public static void main(String[] args) { Cache a1=new Cache(20); //10个生产者 new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); new Thread(new produce(a1)).start(); //10个消费者 new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); new Thread(new consumer(a1)).start(); } }
在这里开始对volatile不是很了解其机制,记得老师讲了i--
的操做三条指令,详细了解了下,具体看: