Java 线程
进程与线程的区别:
1、进程拥有独立的内存地址空间,线程没有。
2、线程是轻量级的进程。
3、线程不能独立存在,它是由进程创建的。
4、真正完成运算任务的是线程。
5、与所属的进程的其它线程共享一个存储空间,使得线程间通信较进程简单。
单CPU某一时刻,只有一个线程在运行
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间;
(2)资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
(3)线程是处理器调度的基本单位,但进程不是.
4)二者均可并发执行.
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
影响:
1、1 / 主频↑ ----- 周期越小,分到的CPU时间片越平均
2、制造工艺,越细越平均。(纳米)
创建线程的方法:
1、A extends Thread(无法让类再继承其它类 单根性 )
2、B implements Runnable(可以共享B类的成员变量,因为 b 的对象时同一个。)
B b = new B();
new Thread(b).start();
new Thread(b).start();
内部类extends Thread 也能共享资源
1 class MyThread 2 { 3 private int index = 0; 4 5 class InnerThread extends Thread 6 { 7 @Override 8 public void run() 9 { 10 System.out.println(++index); 11 } 12 } 13 Thread getThread(){ 14 return new InnerThread(); 15 } 16 }
1 public static void main(String[] args) 2 { 3 MyThread mt = new MyThread(); 4 //同样可以共享 index 变量 5 mt.getThread().start(); 6 mt.getThread().start(); 7 }
设置后台线程:setDaemon( true );
当该线程为守护线程,所正在运行的线程都为守护线程时,Java虚拟机退出,该线程也结束。
线程的同步有两种方法:同步块、同步方法。
每个对象都有一个监视器,或者叫做“锁”。
若是静态方法同步,静态方法只属于类本身,而并不属于某个对象,调用静态方法并不需要创建一个对象。
每个Class也有锁,是这个Class对应的Class对象的锁,同步静态方法就是用方法所在类所对应的Class对象的监视器。
线程的死锁:
线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成死锁。
比如this与obj调用有可能造成死锁。
wait、notify、notifyAll
wait 与 notify 主要用于producer-customer关系中。
wait()------- 在其它线程调用此对象的notify()或notifyAll()前,导致当前线程等待。
notify()------ 唤醒在此对象监视器上等待的单个线程。
notifyAll()---- 唤醒在此对象监视器上等待的所有线程。
1、每个对象除了一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的等待队列是空的。
2、我们应该在当前线程锁住对象的锁后,去调用wait()方法,wait()必须在同步方法或同步块中调用,调用完后进入等待队列当中。
3、当调用对象的notify()时,将从该对象的等待队列中删掉一个任意的线程,这个线程将再次成为可运行的线程。
4、当调用对象的notifyAll()时,将从该对象的等待队列中删掉所有等待的线程,这些线程将成为可运行的线程。
synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行.
1 class Queue 2 { 3 private int value = 0; 4 public boolean isFull = false; 5 6 // synchronized 必须有,不然会报错,保证同一时刻只有一个线程在使用。 7 public synchronized int getValue() 8 { 9 if (!isFull) 10 { 11 try 12 { 13 // 如果队列为空,在customer调用此方法则在等待。 14 wait(); 15 } 16 catch (InterruptedException e) 17 { 18 e.printStackTrace(); 19 } 20 } 21 isFull = false; 22 notify(); 23 return value; 24 } 25 26 // 两个同步方法加的锁的对象都是this,必须是同一个对象。 27 public synchronized void setValue(int value) 28 { 29 // 如果队列未满,放置数据,并通知Customer去获取数据。 30 if (!isFull) 31 { 32 this.value = value; 33 notify(); 34 isFull = true; 35 } 36 try 37 { 38 wait(); // 队列已满,则等待。 39 } 40 catch (InterruptedException e) 41 { 42 e.printStackTrace(); 43 } 44 } 45 }
1 class Producer extends Thread 2 { 3 Queue queue; 4 5 public Producer(Queue queue) 6 { 7 this.queue = queue; 8 } 9 10 @Override 11 public void run() 12 { 13 for (int i = 0; i < 10; i++) 14 { 15 queue.setValue(i); 16 System.out.println("Producer -- " + i); 17 } 18 } 19 }
1 class Customer extends Thread 2 { 3 Queue queue; 4 5 public Customer(Queue queue) 6 { 7 this.queue = queue; 8 } 9 10 @Override 11 public void run() 12 { 13 while (true) 14 { 15 System.out.println("Customer -- " + queue.getValue()); 16 } 17 } 18 }
1 public static void main(String[] args) 2 { 3 Queue queue = new Queue(); 4 Producer producer = new Producer(queue); 5 Customer customer = new Customer(queue); 6 producer.start(); 7 customer.start(); 8 }
Producer
↓1)放数据 ↑4)通知Producer,再重复1)操作
——————————————————————————Queue
↓2)通知Customer ↑3)获取数据
Customer
stop()已Deprecated,因为不安全,一旦调用,会把之前锁住的监视器全都解锁。
线程的终止:
1、设置flag的变量 :
1 class MyThread extends Thread 2 { 3 private boolean isStop = false; 4 5 @Override 6 public void run() 7 { 8 while (!isStop) 9 { 10 System.out.println(getName()); 11 } 12 } 13 14 public void stopThread() 15 { 16 isStop = true; 17 } 18 }
1 public static void main(String[] args) throws InterruptedException 2 { 3 MyThread mt = new MyThread(); 4 mt.start(); 5 Thread.sleep(1000); 6 mt.stopThread(); 7 }
2、结合interrupt()方法:
1 class MyThread extends Thread 2 { 3 4 @Override 5 public synchronized void run() 6 { 7 while (true) 8 { 9 try 10 { 11 wait(); 12 } 13 catch (InterruptedException e) 14 { 15 return; 16 } 17 } 18 } 19 }
1 public static void main(String[] args) throws InterruptedException 2 { 3 MyThread mt = new MyThread(); 4 mt.start(); 5 Thread.sleep(1000); 6 mt.interrupt(); 7 }