ThreadGroup 线程分组类:线程分组类包含的主要属性有分组名,组内线程成员,组内最大线程数,父级分组,子集分组,是否已销毁,是否是守护线程,未启动的线程等
线程池是批量控制激发顺序,线程组是批量控制,比如停止整个线程组
ThreadGroup tg=new ThreadGroup("我的线程组");
Thread t1=new Thread(tg,Demo::method,"线程1");
Thread t2=new Thread(tg,Demo::method,"线程2");
t1.start(); t2.start();
tg.stop();//将线程组中所有线程中断
tg.interrupt();//将线程组中所有线程打上中断标记
td1.setPriorty(3);//设置线程优先级为3
线程优先级:最小是1 最大是10 默认为5
线程的优先级不能超过线程组的优先级
维护现成的手段:1.使用Thread类(调用start,同时使用线程组)
2.使用线程池(需要run和call的实现方案,不需要Thread类)
线程组不负责维护线程,负责线程资源的竞争以及可以对多个线程下达命令
sychrnoized:
//标记方法对象锁
pubic sychronized void show(){} //实例方法 锁标记打在this上
//同步代码块对象锁
public void show2(){
synchronized(this){} //锁标记打在this上
}
//或
public Object obj;
public void show2(){
synchronized(obj){} //锁标记打在Object对象上
}
//标记方法类锁kclass锁
public static sychrnoized void show(){} //静态方法 锁标记打在所在类的kclass上
//同步代码块类kclass锁
pubic void show2(){
sychronized(Object.class){} //锁标记打在指定类的kclass上
}
//最推荐写法:自建锁对象,能分清哪个锁是哪个,不会弄混
static final Object o= new Object();//声明为最终变量,防止中途发生改变导致上锁失败
public void method(){
sychronized(o){}
}
不要使用基本数据类型包装类与String类作为锁对象,因为会涉及到地址变换问题
不上锁的误差>错误上锁的误差
锁粒度:
//锁粒度过大,执行10000次循环代码才能释放锁
sychronized(this){
for(int i=0;i<10000;i++){}
}
//锁粒度过小,需要申请10000次锁
for(int i=0;i<10000;i++){
sychronized(this){}
}
//最优写法
for(int i=0;i<100;i++){
sychronized(this){
for(int j=0;j<100;++){}
}
Thread.yield();//让出cpu执行权
}
Thread.yield():是一个静态方法,会自动判断是哪个线程发起的会使该线程从运行状态转换为就绪状态,然后立刻争抢cpu资源所以可能会出现刚刚放弃后又抢到资源的情况
Thread.sleep(long n) 线程睡眠:使当前线程在指定的毫秒数内休眠(暂停执行),这取决于系统定时器和调度器的精确度和准确性
线程进入阻塞状态,不会释放锁 ,时间到后进入任务队列(就绪状态)