为什么重写run方法?
run是用来封装被线程执行的代码
my1.run()与my1.start()的区别?
线程对象调用run方法不开启线程。仅是对象调用方法。线程对象调用start开启线程,并让jvm调用run方法在开启的线程中执行。
(2)多线程中设置和获取线程名称设置:
(1)my1.setName方法
(2)有参构造,要在thread类中写有参构造方法
获得
(1)在继承的线程类中直接使用getName方法
(2)Thread.currentThread().getName
class MyThread extends Thread { //继承Thread MyThread(String name){ super(name); } //复写其中的run方法 public void run(){ for (int i=1;i<=20 ;i++ ){ System.out.println(Thread.currentThread().getName()+",i="+i); } } } class ThreadDemo { public static void main(String[] args) { //创建两个线程任务 MyThread d = new MyThread(); MyThread d2 = new MyThread(); d.run();//没有开启新线程, 在主线程调用run方法 d2.start();//开启一个新线程,新线程调用run方法 } }(3)多线程的线程调度
l 分时调度
所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。
l 抢占式调度
优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
设置和获取线程优先级
线程默认优先级为5,最小1,最大10
tp1.getPriority()
tp1.setPriority(5)
线程优先级高仅仅表示线程获取cpu时间片的几率高
(4)多线程的线程控制thread.sleep() 使当前执行的线程暂停指定毫秒(线程类中)
t1.join() 等待这个线程死亡后,才执行其他的(测试类里)
t1.setDaemon() 将此线程设置为守护线程,主线程执行完后,运行的都是守护线程时,虚拟机将退出(测试类中)(不会立即死亡)
主线程是main方法,可以设置名字
(5)线程的生命周期 2、多线程的实现之Runnable接口 (1)Runnable接口介绍实现Runnable接口的类就相当于thread的参数,看作资源
在MyRunnable中不能直接使用getName方法
名字作为参数传入
相比继承Thread类,实现Runnable接口的好处
避免了Java单继承的局限性,
适合多个相同程序的代码去处理同一个资源的情况,把线程和 程序的代码、数据有效分离,较好的体现
了面向对象的设计思想
(3)卖票案例的思考出票需要时间,故需要通过sleep方法模拟卖票时间,发现:
相同的票出现多次原因:
某线程苏醒后抢占到cpu的执行权后,输出卖票的语句后,可能还未改变ticket,令一个线程就抢到了cpu的执行权。
出现负数票:线程执行的随机性导致的
3、线程同步 (1)卖票案例为什么出现问题? (2)同步代码块同步代码块:一次只允许一个线程访问这个代码块
注意:括号里面的锁要定义到外面,不能定义到里面,要用同一把锁
同步代码块的好处和弊端:
(3)同步方法同步方法:一次只允许一个线程访问这个方法
同步方法的格式:
在定义这个方法是加关键字,在代码块中加锁
同步方法的锁:是this,把之前的object改为this即可
同步静态方法:一次只允许一个线程访问这个静态方法
同步静态方法的锁:该类的class对象
(4)线程安全的类在多线程的环境下使用的类
就是集合的一些安全类,相当于集合,只不过这些集合的方法线程安全,一次只允许一个线程访问这个方法。
但是:也可以通过这个方法将map,list变成线程安全类
(5)Lock锁创建lock锁:
将lock锁加到代码块中:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)