java 多线程 之Thread

参考博客

Java多线程学习(总结很详细!!!)

根据java 8关于thread的介绍:

有两种方法可以创建线程

第一种是继承Thread ,需要重写Thread的run方法

class PrimeThread extends Thread {
    long minPrime;
    PrimeThread(long minPrime) {
        this.minPrime = minPrime;
    }
 
    public void run() {
        // compute primes larger than minPrime
         . . .
    }
}

 以下代码将创建一个线程并开始运行

 PrimeThread p = new PrimeThread(143);
 p.start();

 另一个方法是implements Runable 接口

class PrimeRun implements Runnable {
    long minPrime;
    PrimeRun(long minPrime) {
         this.minPrime = minPrime;
    }
 
    public void run() {
        // compute primes larger than minPrime
         . . .
    }
}
 PrimeRun p = new PrimeRun(143);
 new Thread(p).start();

今天就说一下Thread与Runable

public class Thread implements Runnable

//返回当前正在执行的线程的引用
public static native Thread currentThread();

//使当前线程从执行状态(运行状态)变为可执行态(就绪状态),但还可能会继续执行当前线程
public static native void yield();

//正在执行的线程进入休眠状态(暂时停止执行)
//millis 休眠时间 毫秒 >=0
public static native void sleep(long millis) throws InterruptedException;

//指定毫秒数以及纳秒数
public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }
//分配一个新的Thread对象
public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }

//
 public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

//name 新线程的name
public Thread(String name) {
        init(null, null, name, 0);
    }


public class Thread1 extends Thread {
	
	
	@Override
	public void run() {
		for(int i = 0;i < 5;i++) {
			System.out.println(Thread.currentThread().getName()+": "+i);
		}
	}
	
	
}



/**
 * start()方法的调用后并不是立即执行多线程代码,而是使得该线程变为可运行态(Runnable),什么时候运行是由操作系统决定的。
 * @author yifei.Wang
 *
 */
public class Main {

	public static void main(String[] args) {
		Thread1 mTh1 = new Thread1();
		Thread1 mTh2 = new Thread1();
		mTh1.start();
		mTh2.start();
		//mTh2.start(); 重复调用会出异常

	}

}
public class Thread1 implements Runnable {
	
	@Override
	public void run() {
		for(int i = 0;i < 5;i++) {
			System.out.println(Thread.currentThread().getName()+": "+i);
		}
	}
	
}

public class Main {

	public static void main(String[] args) {
		Thread1 tq = new Thread1();
		new Thread(tq).start();
		new Thread(tq).start();
	}

}

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

因为有多个Thread,那么就要new 多个 Thread 因为有共享资源,所以资源必须是static修饰的

例如

public class Thread2 extends Thread {
	
	static int m = 10;
	@Override
	public void run() {
		for(int i = 0;i < 5;i++) {
			m--;
			System.out.println(Thread.currentThread().getName()+": "+i+": "+m);
		}
	}
}


public class Main {

	public static void main(String[] args) {
		Thread2 t1 = new Thread2();
		Thread2 t2 = new Thread2();
		Thread2 t3 = new Thread2();
		Thread2 t4 = new Thread2();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}

}

但是 如果使用Runnable

public class Thread1 implements Runnable {
	
	private int m = 10;
	@Override
	public void run() {
		for(int i = 0;i < 5;i++) {
			m--;
			System.out.println(Thread.currentThread().getName()+": "+i+": "+m);
		}
	}
	
}

public class Main2 {

	public static void main(String[] args) {
		Thread1 thread1 = new Thread1();
		new Thread(thread1).start();
		new Thread(thread1).start();
		new Thread(thread1).start();
		new Thread(thread1).start();
	}

}

则不需要设置 静态变量了,因为我们一直用一个Thread1  没有new 多个Thread1 ,也可以说,如果我们new 多个Thread1 ,那么使用private就不行了

发现 Thread也实现了Runnable接口,Runnable接口里只有一个run方法

启动线程的时候就会调用run方法

public interface Runnable {

    public abstract void run();

}

java中线程是有优先级的

 /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

//设置优先级
public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

// 获取优先级
 public final int getPriority() {
        return priority;
    }

但在上边的例子中,发现,主线程一直比子线程结束的早。Java中主线程结束后子线程继续运行,但C中会报错

所以用到了join方法

//等待线程die,只有这个线程结束后才能继续执行后面的程序
public final void join() throws InterruptedException {
        join(0);
    }

//设置时间,若为0的话,永远等待
public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }


 public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }
public class Main2 {

	public static void main(String[] args) {
		Thread1 thread1 = new Thread1();
		Thread t1 = new Thread(thread1);
		Thread t2 = new Thread(thread1);
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(Thread.currentThread().getName()+"主线程结束");
	}

}

这样的话,主线程必须等这两个线程全结束才能结束

yield() 暂停当前正在执行的对象,并执行其他线程,只是让当前线程转换为可执行状态,以允许具有相同优先级的线程获得运行机会,但无法保证yield达到让步的目的。

sleep() 使当前线程进入停滞状态,所以执行sleep的线程在指定时间内肯定不会被执行

sleep()方法允许较低有优先级的线程获取运行机会,但yield()不会

Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。相应的notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。

但是  synchronized 到底是什么?

猜你喜欢

转载自blog.csdn.net/qq_35815781/article/details/85683364