南通网站建设seo,营销最好的网站建设公司,合肥最好的网站建设公司排名,在线制作店铺logo图标免费一、方式1#xff1a;继承Thread类
步骤#xff1a;
创建一个继承于Thread类的子类重写Thread类的run()方法 ---- 此线程执行的操作声明在方法体中创建当前Thread子类的对象通过实例对象调用start()方法#xff0c;启动线程 ---- Java虚拟机会调用run()方法
注意…一、方式1继承Thread类
步骤
创建一个继承于Thread类的子类重写Thread类的run()方法 ---- 此线程执行的操作声明在方法体中创建当前Thread子类的对象通过实例对象调用start()方法启动线程 ---- Java虚拟机会调用run()方法
注意main()方法是主线程
1. 创建线程
//自定义线程类
public class MyThread extends Thread {// 共享数据要放在run()方法外边才能被共享且声明为static否则就是每个线程都会调用run()方法都会单独拥有一个run()方法里的独享数据而非共享数据//eg: static int trick 100;//定义指定线程名称的构造方法public MyThread(String name) {//调用父类的String参数的构造方法指定线程的名称super(name);}/*** 重写run方法完成该线程执行的逻辑*/Overridepublic void run() {// 执行的操作}
}2. 调用线程
public class TestMyThread {public static void main(String[] args) {//创建自定义线程对象1MyThread mt1 new MyThread(子线程1);//开启子线程1mt1.start();//创建自定义线程对象2分别创建对象开启线程不可以数据共享若要共享需要创建static变量MyThread mt2 new MyThread(子线程2);//开启子线程2mt2.start();}
}3. 创建Thread类的匿名子类的匿名对象
// 创建Thread类的匿名子类的匿名对象并启动线程
new Thread(){public void run(){// 执行的操作}
}.strat(); // 启动线程二、方式2实现Runnable接口
创建一个实现Runnable接口的类实现接口中的run()方法 ---- 线程执行的操作声明在此方法中创建实例对象将此对象作为参数传到Thread类的构造器中创建Thread类的实例通过Thread的实例对象调用strat()方法启动线程 ---- Java虚拟机会调用run()方法
最终还是通过Thread实现的
1. 创建线程
public class MyRunnable implements Runnable {// 共享数据要放在run()方法外边才能被共享否则就是每个线程都会调用run()方法都会单独拥有一个run()方法里的独享数据而非共享数据//eg: int trick 100;Overridepublic void run() {// 执行的操作}
}2. 调用线程
public class TestMyRunnable {public static void main(String[] args) {//创建自定义类对象 线程任务对象MyRunnable mr new MyRunnable();//创建线程对象1Thread t1 new Thread(mr, 长江1);t1.start();//创建线程对象2注意两个线程传入的是同一个对象可以实现数据共享Thread t2 new Thread(mr, 长江2);t2.start();}
}3. 创建Runnable接口的匿名子类的匿名对象
new Thread(new Runnable(){public run(){// 执行的操作}
}).start(); // 开启线程三、继承Thread类 VS 实现Runnable接口
1. 共同点
都是通过Thread类中定义的start()来启动线程。都是通过Thread类或其子类的实例对象来创建线程。
2. 不同点
Thread是继承Runnable是实现
3. Runnable好处
通过实现的方式避免了类的单继承的局限性自动共享数据更适合处理有共享数据的业务逻辑实现了逻辑代码在run()方法中和数据在创建线程的方法中的分离
四、Thread类常用方法和生命周期
1. 构造器
构造器描述public Thread()分配一个新的线程对象。public Thread(String name)分配一个指定名字的新的线程对象。public Thread(Runnable target)指定创建线程的目标对象它实现了Runnable接口中的run方法public Thread(Runnable target,String name)分配一个带有指定目标新的线程对象并指定名字。
2. 常用方法——线程设置
构造器描述public void run()此线程要执行的任务在此处定义代码。public void start()导致此线程开始执行; Java虚拟机调用此线程的run方法。public String getName()获取当前线程名称。public void setName(String name)设置该线程名称。public static Thread currentThread()返回对当前正在执行的线程对象的引用。在Thread子类中就是this通常用于主线程和Runnable实现类public static void sleep(long millis)使当前正在执行的线程以指定的毫秒数暂停暂时停止执行。public static void yield()主动释放当前线程的执行权一旦执行就释放CPU的执行权yield只是让当前线程暂停一下让系统的线程调度器重新调度一次希望优先级与当前线程相同或更高的其他线程能够获得执行机会但是这个不能保证完全有可能的情况是当某个线程调用了yield方法暂停之后线程调度器又将其调度出来重新执行。
3. 常用方法——阻塞线程
构造器描述public final boolean isAlive()测试线程是否处于活动状态。如果线程已经启动且尚未终止则为活动状态。void join()阻塞其他线程在线程a中通过线程b调用join()意味着线程a进入阻塞状态直到线程b执行结束线程a才结束阻塞状态。等待该线程终止。void join(long millis)阻塞其他线程阻塞其他线程的时间最长为 millis 毫秒。如果millis时间到将不再等待。void join(long millis, int nanos)阻塞其他线程阻塞其他线程的时间最长为 millis 毫秒 nanos 纳秒。public final void stop()已过时不建议使用。强行结束一个线程的执行直接进入死亡状态。run()即刻停止可能会导致一些清理性的工作得不到完成如文件数据库等的关闭。同时会立即释放该线程所持有的所有的锁导致数据得不到同步的处理出现数据不一致的问题。void suspend() / void resume()这两个操作就好比播放器的暂停和恢复。二者必须成对出现否则非常容易发生死锁。suspend()调用会导致线程暂停但不会释放任何锁资源导致其它线程都无法访问被它占用的锁直到调用resume()。已过时不建议使用。
4. 常用方法——优先级
每个线程都有一定的优先级同优先级线程组成先进先出队列先到先服务使用分时调度策略。优先级高的线程采用抢占式策略获得较多的执行机会。每个线程默认的优先级都与创建它的父线程具有相同的优先级。
构造器描述MAX_PRIORITY10三个优先级常量之一最高优先级MIN _PRIORITY 1三个优先级常量之一最低优先级NORM_PRIORITY 5三个优先级常量之一普通优先级默认情况下main线程具有普通优先级。public final int getPriority()返回线程优先级public final void setPriority(int newPriority)改变线程的优先级范围在[1,10]之间。
5. 线程的生命周期
jdk1.5 之前的5种状态 jdk1.5 之后的6种状态
将准备和运行合并为一个Runnable状态将阻塞细分为计时等待、锁阻塞、无线等待3种状态
五、解决线程的安全问题
当多个线程同时操作同一个共享数据时就会出现线程的安全问题。
方式一同步代码块
/**
* 1.同步监视器俗称锁。哪个线程获得了锁哪个线程就能执行该代码块
* 2.同步监视器可以是任何一个类的对象。但是多个线程必须共用同一个同步监视器且该对象是唯一的只有一个实例对象。
* 可以自定义一个专用于线程锁的类然后在这里创建对象作为锁使用。
* 可以使用this充当锁this指向当前对象。但是要注意当前类是否只创建了一个对象保证唯一性
* 在继承Thread的方式中不可以使用this因为每一个线程都需要创建对象不满足唯一性
* 在继承Thread的方式中创建对象作为锁也需要声明为static的才可以static Object obj new Pbject();
* 可以使用“当前类.class”充当锁。因为“Class clz 类.class”是一个类仅加载一次是全局唯一的反射该方式在实现Runnable中也可以使用
*
*/
synchronized(同步监视器){// 需要被同步的代码即操作共享数据的代码
}方式二同步方法
/*
*用synchronized 直接修饰操作同步代码的方法
* 1.在非static的方法中默认锁是this。锁无法修改因而在继承Thread方法中不适用可以改成同步代码块方式手动添加将当前类做为锁
* 2.在static的方法中默认的锁是当前类.class。即当前类本身。
*
*/
// 示例代码在run()方法中调用show()方法
public synchronized void show(){// 操作共享数据的代码
}