• JAVA基础--线程


    sleep和wait的区别:

    1. sleep是Thread的方法, wait是object的方法

    2.  sleep占着CPU睡觉, wait等待CPU,不占用CPU

    线程是一个程序内部的顺序控制流

    线程和进程的区别:

    1. 每个进程都有独立的代码和数据空间, 进程间的切换会有很大的开销.

    2. 线程可以看成是轻量级的进程, 同一类线程共享代码和数据空间, 每个线程有独立的运行栈和程序计数器PC, 线程切换的开销小.

    3. 多进行, 在操作系统中能同时运行多个任务(程序)

    4. 多线程:在同一个程序可以有多个顺序刘同时执行.

    通过创建Thread的实例来创建新的线程

    每个线程都通过特定Thread对象对应的run方法来完成操作, 方法run称为线程体

    通过调用Thread类的start方法启动一个线程

    run是方法调用,start是开启一个线程

    以下程序只有一个线程 main, 主线程

    public class {
    	public static void main(String[] args) {
    		m1();
    	}
    	
    	public static  void m1() {
    		m2();
    		m3();
    	}
    	
    	public static void m2() {}
    	public static void m3() {}
    }
    

    进程: 一个class文件, 一个exe文件, 是个静态的概念.进程的执行指的是一个主线程开始执行, 即main开始.

    所以机器里我们运行的都是线程.

    建议使用以下接口的方式:

    public class TestThread1 {
    	public static void main(String args[]) {
    		Runner1 r = new Runner1();		
    		Thread t = new Thread(r);
    		t.start();		
    		for(int i=0; i<100; i++) {
    			System.out.println("Main Thread:------" + i);
    		}
    	}
    }
    
    class Runner1 implements Runnable {
    	public void run() {
    		for(int i=0; i<100; i++) {	
    			System.out.println("Runner1 :" + i);
    		}
    	}
    }
    

    还有一种方法,继承Thread,不建议使用:

    public class TestThread1 {
    	public static void main(String args[]) {
    		Runner1 r = new Runner1();
    		r.start();
    		for(int i=0; i<100; i++) {
    			System.out.println("Main Thread:------" + i);
    		}
    	}
    }
    
    class Runner1 extends Thread {
    	public void run() {
    		for(int i=0; i<100; i++) {	
    			System.out.println("Runner1 :" + i);
    		}
    	}
    }
    

      

    线程状态转换:

    创建-->start-->就绪--> 运行-->终止  运行-->阻塞状态-->就绪 

    线程控制的方法:

    isAlive():  阻塞,运行, 就绪,  

    getPriority() 获得优先级

    setPriority(): 设置优先级

    Thread.sleep(): 将当前线程睡眠指定毫秒数

    join(): 合并, 等改线程结束再恢复当前线程的运行

    yield(): 让出CPU, 当前线程进去就绪状态等待调度

    wait(): 当前线程进入wait pool

    sleep方法: Thread类的静态方法:

    import java.util.*;
    public class TestInterrupt {
      public static void main(String[] args) {
        Runner r = new Runner();
        Thread t = new Thread(r);
        t.start();
        try {Thread.sleep(10000);}
        catch (InterruptedException e) {}
        //t.interrupt();  //打断子线程,比较粗暴
    r.flag=false; //替换上面的打断子线程的方式, 用这种方式, run方法里的return也可以注释掉了 } } class Runner implements Runnable {    boolean flag = true;   public void run(){ while(flag){ System.out.println("==="+new Date()+"==="); try { Thread.sleep(1000); } catch (InterruptedException e) { //被打算后进入异常, return return; } } } }

    结果:每隔一秒显示一次:

    ===Fri Apr 08 10:53:44 CST 2016===
    ===Fri Apr 08 10:53:45 CST 2016===
    ===Fri Apr 08 10:53:46 CST 2016===
    ===Fri Apr 08 10:53:47 CST 2016===
    ===Fri Apr 08 10:53:48 CST 2016===
    ===Fri Apr 08 10:53:49 CST 2016===
    ===Fri Apr 08 10:53:50 CST 2016===
    ===Fri Apr 08 10:53:51 CST 2016===
    ===Fri Apr 08 10:53:52 CST 2016===
    ===Fri Apr 08 10:53:53 CST 2016===
    

      

    join用法:相当于调用, 如果main里调用join, 那么会等join的线程执行完才能执行自己的线程:

    public class TestJoin {
      public static void main(String[] args) {
        MyThread2 t1 = new MyThread2("abcde");
        t1.start();
        try {
        	t1.join();
        } catch (InterruptedException e) {}
        	
        for(int i=1;i<=10;i++){
          System.out.println("i am main thread");
        }
      }
    }
    class MyThread2 extends Thread {
      MyThread2(String s){
      	super(s);
      }
      
      public void run(){
        for(int i =1;i<=10;i++){
          System.out.println("i am "+getName());
          try {
          	sleep(1000);
          } catch (InterruptedException e) {
          	return;
          }
        }
      }
    }
    

    结果:

    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am abcde
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    i am main thread
    

      

    yield方法: 让出CPU, 给其他线程执行的机会:

    只要运行的线程 i 被10整除, 就让出给别的线程运行

    public class TestYield {
      public static void main(String[] args) {
        MyThread3 t1 = new MyThread3("t1");
        MyThread3 t2 = new MyThread3("t2");
        t1.start(); t2.start();
      }
    }
    class MyThread3 extends Thread {
      MyThread3(String s){super(s);}
      public void run(){
        for(int i =1;i<=100;i++){
          System.out.println(getName()+": "+i);
          if(i%10==0){
            yield();
          }
        }
      }
    }
    

      

    线程的优先级:

    public class TestPriority {
    	public static void main(String[] args) {
    		Thread t1 = new Thread(new T1());
    		Thread t2 = new Thread(new T2());
    		t1.setPriority(Thread.NORM_PRIORITY + 3);
    		t1.start();
    		t2.start();
    	}
    }
    
    class T1 implements Runnable {
    	public void run() {
    		for(int i=0; i<100; i++) {
    			System.out.println("T1: " + i);
    		}
    	}
    }
    
    class T2 implements Runnable {
    	public void run() {
    		for(int i=0; i<100; i++) {
    			System.out.println("------T2: " + i);
    		}
    	}
    }
    
    Thread.MIN_PRIORITY=1;
    
    Thread.MAX_PRIORITY=10;
    
    Thread.NORM_PRIORITY=5;
    

      

    同一个线程对象可以定义两个Thread:

    public class TestThread2 {
    	public static void main(String args[]) {
    		Runner2 r = new Runner2();
    		Thread t1 = new Thread(r);
    		Thread t2 = new Thread(r);
    		t1.start();
    		t2.start();
    	}
    }
    
    class Runner2 implements Runnable {
    	public void run() {
    		for(int i=0; i<30; i++) {	
    			System.out.println("No. " + i);
    		}
    	}
    }
    

    被10整除就停顿2s:

    public class TestThread3{
    	public static void main(String args[]) {
    		Runner3 r = new Runner3();
    		Thread t = new Thread(r);
    		t.start();
    	}
    }
    
    class Runner3 implements Runnable {
    	public void run() {
    		for(int i=0; i<30; i++) {	
    			if(i%10==0 && i!=0) {
    				try{
    					Thread.sleep(2000); 
    				}catch(InterruptedException e){}
    			}
    			System.out.println("No. " + i);
    		}
    	}
    }
    

    如何恰当的结束线程, 用flag:

    public class TestThread4 {	
    	public static void main(String args[]){
    		Runner4 r = new Runner4();
           	Thread t = new Thread(r);
            t.start();
            for(int i=0;i<100000;i++){
            	if(i%10000==0 & i>0)
            		System.out.println("in thread main i=" + i);
            }
            System.out.println("Thread main is over");
            r.shutDown();
            //t.stop();
        }
    }
    
    class Runner4 implements Runnable {
      private boolean flag=true;
      
    	public void run() {
    		int i = 0;
    		while (flag==true) {
    			System.out.print(" " + i++);	
    		}
    	}
    	
      public void shutDown() {
    		flag = false;
      }
    }
    

    isAlive:

    public class TestThread6 {	
    	public static void main(String args[]){
    		Thread t = new Runner6();
       		t.start();		
    		for(int i=0; i<50; i++) {
    			System.out.println("MainThread: " + i);
    		}
      }
    }
    
    class Runner6 extends Thread {
    	public void run() {
    		System.out.println(Thread.currentThread().isAlive());
    		for(int i=0;i<50;i++) {
    			System.out.println("SubThread: " + i);
    		}
    	}
    }
    

     线程同步: synchronized:

    执行方法的过程中当前对象被锁定, 这样对象控制一个过程, 别的线程不可打扰.

    public class TestSync implements Runnable {
      Timer timer = new Timer();
      public static void main(String[] args) {
        TestSync test = new TestSync();
        Thread t1 = new Thread(test);
        Thread t2 = new Thread(test);
        t1.setName("t1"); 
        t2.setName("t2");
        t1.start(); 
        t2.start();
      }
      public void run(){
        timer.add(Thread.currentThread().getName());
      }
    }
    
    class Timer{
      private static int num = 0;
      public synchronized void add(String name){    //执行方法的过程中锁定当前对象
      	 //synchronized (this) {                //方法不加同步的话, 可以用此方法体的方式锁定
    	    num ++;
    	    try {Thread.sleep(1);} 
    	    catch (InterruptedException e) {}
    	    System.out.println(name+", 你是第"+num+"个使用timer的线程");
    	 //}
      }
    }
    

    结果:

    不加synchronized的话, 就都显示2

    t1, 你是第1个使用timer的线程
    t2, 你是第2个使用timer的线程
    

      

    用synchronize的时候会出现死锁的现象,比如线程A执行过程中,锁定某一个对象1.   另一个线程B锁定另一个对象2, 线程A 需要继续锁定对象2, 线程B需要锁定对象1, 就会发生死锁.

    public class TestDeadLock implements Runnable {
    	public int flag = 1;
    	static Object o1 = new Object(), o2 = new Object();
    	public void run() {
    	System.out.println("flag=" + flag);
    		if(flag == 1) {
    			synchronized(o1) {
    				try {
    					Thread.sleep(500);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    				synchronized(o2) {
    					System.out.println("1");	
    				}
    			}
    		}
    		if(flag == 0) {
    			synchronized(o2) {
    				try {
    					Thread.sleep(500);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    				synchronized(o1) {
    					System.out.println("0");
    				}
    			}
    		}
    	}	
    	
    	public static void main(String[] args) {
    		TestDeadLock td1 = new TestDeadLock();
    		TestDeadLock td2 = new TestDeadLock();
    		td1.flag = 1;
    		td2.flag = 0;
    		Thread t1 = new Thread(td1);
    		Thread t2 = new Thread(td2);
    		t1.start();
    		t2.start();
    		
    	}
    }
    

    结果: 线程不动了:

    flag=1
    flag=0
    

    线程锁死后, 别的方法还可以访问

    public class TT implements Runnable {
    	int b = 100;
    	
    	public synchronized void m1() throws Exception{
    		b = 1000;
    		Thread.sleep(5000);
    		System.out.println("b = " + b);
    	}
    	
    	public  void m2() {
    		System.out.println(b);
    	}
    	
    	public void run() {
    		try {
    			m1();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception {
    		TT tt = new TT();
    		Thread t = new Thread(tt);
    		t.start();
    		Thread.sleep(1000);
    		tt.m2();
    	}
    }
    

    结果:

    1000
    b = 1000
    

    上例子改一下:

    public class TT implements Runnable {
    	int b = 100;
    	
    	public synchronized void m1() throws Exception{
    		b = 1000;
    		Thread.sleep(5000);
    		System.out.println("b = " + b);
    	}
    	
    	public void m2() throws Exception {
    		Thread.sleep(2500);
    		b = 2000;
    	}
    	
    	public void run() {
    		try {
    			m1();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception {
    		TT tt = new TT();
    		Thread t = new Thread(tt);
    		t.start();
    		
    		tt.m2();
    		System.out.println(tt.b);
    	}
    }
    

    结果:

    2000
    b = 2000
    

    再改一下:

    1. 先执行m2, 执行完后

    2. m1 执行 b=1000;

    3. 主线程执行 输出b

    4. m1 执行 输出b=1000;

    public class TT implements Runnable {
    	int b = 100;
    	
    	public synchronized void m1() throws Exception{
    		b = 1000;		
    		Thread.sleep(5000);
    		System.out.println("b = " + b);
    	}
    	
    	public synchronized void m2() throws Exception {
    		Thread.sleep(2500);
    		b = 2000;
    	}
    	
    	public void run() {
    		try {
    			m1();
    		} catch(Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void main(String[] args) throws Exception {
    		TT tt = new TT();
    		Thread t = new Thread(tt);
    		t.start();
    		tt.m2();		
    		System.out.println(tt.b);	
    	}
    }
    

    结果:

    1000
    b = 1000

      

    wait必须和synchronized同时出现, 不能单独使用wait, wait是object类的方法.

    wait的时候锁不归我所有, sleep的时候, 还抱着锁.

    wait后需要notify叫醒, 也是object类的方法

    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 "WoTou : " + 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) {
    				e.printStackTrace();
    			}
    		}
    		this.notifyAll();		
    		arrWT[index] = wt;
    		index ++;
    	}
    	
    	public synchronized WoTou pop() {
    		while(index == 0) {
    			try {
    				this.wait();
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    		this.notifyAll();
    		index--;
    		return arrWT[index];
    	}
    }
    
    class Producer implements Runnable {
    	SyncStack ss = null;
    	Producer(SyncStack ss) {
    		this.ss = ss;
    	}
    	
    	public void run() {
    		for(int i=0; i<10; i++) {
    			WoTou wt = new WoTou(i);
    			ss.push(wt);
    			System.out.println("生产了:" + wt);
    			try {
    				Thread.sleep((int)(Math.random() * 200));
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}			
    		}
    	}
    }
    
    class Consumer implements Runnable {
    	SyncStack ss = null;
    	Consumer(SyncStack ss) {
    		this.ss = ss;
    	}
    	
    	public void run() {
    		for(int i=0; i<10; i++) {
    			WoTou wt = ss.pop();
    			System.out.println("消费了: " + wt);
    			try {
    				Thread.sleep((int)(Math.random() * 1000));
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}			
    		}
    	}
    }
    

      

      

      

      

      

  • 相关阅读:
    将课程中的所有动手动脑的问题以及课后实验性的问题,整理成一篇文档,以博客形式发表在博客园
    将课程中的所有动手动脑的问题以及课后实验性的问题,整理成一篇文档
    课堂作业 异常与处理
    课堂作业05继承与多态
    课后作业04
    课堂作业03程序设计
    课堂作业03动手动脑问题
    课堂作业02程序设计作业
    课堂作业02动手动脑的问题
    课堂中所有的问题及其课后实验性的问题的文档
  • 原文地址:https://www.cnblogs.com/wujixing/p/5360898.html
Copyright © 2020-2023  润新知