线程是一个程序内部的顺序控制流。
线程和进程的区别:
每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
多进程:在操作系统中能同时运行多个任务(程序)
多线程:在同一应用程序中有多个顺序流同时执行
当多线程sleep时,如何停止呢?
1、interrupt()方法,这个方法很粗暴不建议使用,这个相当于睡觉的时候一盆凉水泼下来,会抛出interruptedException。
2、stop()方法,已经废弃了,这个比interrupt更粗暴,直接停止线程。不建议使用。
3、用标量在外部控制。
join方法:合并某个线程。把处于并行运行状态的线程合并到当前线程中。
yield()方法:让出CPU,给其他线程执行的机会。
setPriority():设置优先级,优先级越高,cpu分得时间片就越多,越容易得到执行。
线程同步:在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记。这个标记保证在任何一个时刻,只能有一个线程访问该对象。
关键字synchronized来与对象的互斥锁联系。当某个对象synchronized修饰时,表明该对象在任一时刻只能由一个线程访问。synchronized可以作为关键字设在方法上,也可以使用synchronized(this){}中表明锁定该对象的内容。
尽量只锁定一个对象,避免死锁。
当一个线程锁定了一个方法的时候,其他线程可以通过其他方法修改值,所以,一定要保证所有有关这个变量的方法都要加锁。
同步实例:
[html] view plain copy
- <span style="font-family:Microsoft YaHei;"><span style="font-size:12px;">package thread;
- public class TT implements Runnable{
- int b = 100 ;
- @Override
- public void run() {
- m1() ;
- }
- //只会锁定m1方法内的内容,不会锁定b
- public synchronized void m1() {
- b = 1000 ;
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("b = " + b);
- }
- public void m2() {
- System.out.println(b);
- }
- public static void main(String[] args) {
- TT t = new TT() ;
- Thread thread = new Thread(t) ;
- thread.start() ;
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t.m2();
- }
- }
- </span></span>
生产者与消费者实例:
[html] view plain copy
- <span style="font-family:Microsoft YaHei;">package thread;
- public class ProducerConsumer {
- public static void main(String[] args) {
- SyncStack ss = new SyncStack() ;
- Producer p = new Producer(ss) ;
- Consumer c = new Consumer(ss) ;
- new Thread(p).start();
- new Thread(c).start();
- }
- }
- class WoTou {
- int id ;
- WoTou(int id) {
- this.id = id ;
- }
- public String toString() {
- return "id = " + this.id ;
- }
- }
- class SyncStack {
- int index = 0 ;
- WoTou[] arrWt = new WoTou[6] ;
- public synchronized void push(WoTou wt) {
- while(index == arrWt.length) {
- try {
- this.wait();
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- this.notify();
- arrWt[index] = wt ;
- index ++ ;
- }
- public synchronized WoTou pop() {
- while(index == 0) {
- try {
- this.wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- this.notify();
- index -- ;
- return arrWt[index] ;
- }
- }
- class Producer implements Runnable {
- SyncStack s = null ;
- public Producer(SyncStack s) {
- this.s = s ;
- }
- @Override
- public void run() {
- for(int i=0; i<20; i++) {
- WoTou wt = new WoTou(i) ;
- System.out.println("push : " + wt);
- s.push(wt);
- }
- }
- }
- class Consumer implements Runnable {
- SyncStack s = null ;
- public Consumer(SyncStack s) {
- this.s = s ;
- }
- @Override
- public void run() {
- for(int i=0; i<20; i++) {
- WoTou wt = s.pop() ;
- System.out.println("pop : " + wt);
- }
- }
- }</span>
wait和sleep的区别
wait时别的线程可以访问锁定对象,调用wait方法的时候必须锁定该对象。sleep时别的线程也不可以访问锁定对象。