4、java.lang.Thread线程类
public class Thread implements Runnable{//变量-------------------------------------private Runnable target;private charname[];//字段-------------------------------------//线程可以具有的最低优先级。public final static int MIN_PRIORITY = 1;//分配给线程的默认优先级。 public final static int NORM_PRIORITY = 5;//线程可以具有的最高优先级。 public final static int MAX_PRIORITY = 10;//构造方法----------------------------------//1,构造方法:分配新的 Thread 对象。public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0); }//2,构造方法public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0); }//3,构造方法public Thread(String name) {init(null, null, name, 0); }//4,构造方法public Thread(Runnable target, String name) {init(null, target, name, 0); }//方法---------------------------------------//1,如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。public void run() {if (target != null) {target.run();} }//2,使该线程开始执行;Java 虚拟机调用该线程的 run 方法。public synchronized void start() { if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) {stop0(throwableFromStop);} } private native void start0();//3,返回该线程的字符串表示形式,包括线程名称、优先级和线程组。public String toString() { ThreadGroup group = getThreadGroup();if (group != null) {return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";} else {return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";} }//4,返回该线程的名称。public final String getName() {return String.valueOf(name); }//5,返回该线程的标识符。public long getId() { return tid; }//6,返回线程的优先级。public final int getPriority() {return priority; }//7,中断线程。public void interrupt() {//......... }//8,等待该线程终止。public final void join() throws InterruptedException {join(0); }//等待该线程终止的时间最长为 millis 毫秒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);//等待方法继承自Object}} else {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);//等待方法继承自Objectnow = System.currentTimeMillis() - base;}} }//等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。public final synchronized void join(long millis, int nanos)throws InterruptedException {}//9,将该线程标记为守护线程或用户线程。public final void setDaemon(boolean on) {checkAccess();if (isAlive()) {throw new IllegalThreadStateException();}daemon = on; }//10,改变线程名称,使之与参数 name 相同。public final void setName(String name) {checkAccess();this.name = name.toCharArray(); }//11,更改线程的优先级。public final void setPriority(int newPriority) { //......... }//12,在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。public static native void sleep(long millis) throws InterruptedException;//在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响public static void sleep(long millis, int nanos) throws InterruptedException//....经过运算得出最终millissleep(millis); }//13,暂停当前正在执行的线程对象,并执行其他线程。public static native void yield();//14,返回对当前正在执行的线程对象的引用。public static native Thread currentThread();}
?三、创建线程的第一种方式:继承Thread类
?
?
class Demo extends Thread{public void run(){for(int x=0;x<60;x++)System.out.println("demo run:"+x);}}class ThreadDemo{public static void main(String[] args){Demo d = new Demo();d.start();for(int x=0;x<60;x++)System.out.println("main run:--------"+x);}}发现上面代码运行结果每一次都不同因为多个线程都在获取cpu的执行权,cpu执行到谁,谁就运行明确一点,在某一个时刻,只能有一个程序在运行,(多核除外)Cpu在做着快速的切换,以达到看上去是同时运行的效果我们可以形象的把多线程的运行形容为在互相抢夺cpu的执行权这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多久,cpu说了算
四、为什么要覆盖run方法呢?
?
Thread类用于描述线程该类就定义了一个用于存储线程要运行的代码的功能,该存储功能就是run方法,也就是说Thread类中的run方法,用于存储线程要运行的代码示例:class Demo extends Thread{Demo(String name){super(name);//设置线程名称}public void run(){for(int x=0;x<60;x++)System.out.println(Thread.currentThread().getName()+x);}}class ThreadDemo{public static void main(String[] args){Demo d = new Demo("haha");d.start();Demo d1 = new Demo("heihei");d1.start();for(int x=0;x<60;x++)System.out.println(Thread.currentThread().getName()+"---"+x);}}
?
线程默认的名称:Thread-编号 该编号从 0 开始设置线程名称: setName()或者构造函数(super())五、创建线程的第二种方式:实现Runnable接口
?
public interface Runnable { //此接口只有这么一个成员 /** *Runnable
接口应该由那些打算通过某一线程执行其实例的类来实现。 * 设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。 * 例如,Thread
类实现了Runnable
。 * 激活的意思是说某个线程已启动并且尚未停止。 * <p> * 此外,Runnable
为非Thread
子类的类提供了一种激活方式。 * 通过实例化某个Thread
实例并将自身作为运行目标, * 就可以运行实现Runnable
的类而无需创建Thread
的子类。 * @see java.lang.Thread#run() */ public abstract void run();}
?六、实现方式和继承方式的区别?
?
实现方式避免了单继承的局限性继承Thread:线程代码存放在Thread子类run方法中实现Runnable:线程代码存在接口的子类的run方法中在定义线程时,建议使用实现方式七、示例
?
/**需求:买车票*/class Ticket implements Runnable{private int tick = 100;public void run(){while(true){if(tick > 0){try{Thread.sleep(10);}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"::"+tick);}}}}class ThreadDemo{public static void main(String[] args){Ticket t = new Ticket();new Thread(t).start();new Thread(t).start();new Thread(t).start();new Thread(t).start();new Thread(t).start();}}结果可能会出现0 -1 -2 等错票多线程的运行出现了安全问题这里写Thread.sleep(10);是模仿进程特别多的时候出现的情况
八、同步代码块
?
问题原因:当多条语句在操作共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误解决方法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行Java对于多线程的安全问题提供了专业的解决方式:就是同步代码块格式:synchronized(Object){//需要被同步的代码}?所以上面的代码可以优化如下:
class Ticket implements Runnable{private int tick = 100;Object obj = new Object();public void run(){while(true){synchronized(obj){if(tick > 0){try{Thread.sleep(10);}catch(Exception e){}System.out.println(Thread.currentThread().getName()+"::"+tick--);}}}}}?obj如同锁,持有锁的线程可以在同步中执行没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁同步的前提:必须要有两个或者两个以上的线程使用同一个锁好处:解决了多线程的安全问题弊端:多个线程需要判断锁,较为消耗资源
九、同步函数
?
如:
class Bank{private int sum;public synchronized void add(int n){sum += n;System.out.println("sum:"+sum);}}
?
十、死锁
?
? ? 同步中嵌套同步的时候,容易发生死锁
?