JAVA学习笔记(四十一)-多线程与线程组

时间:2021-10-05 11:28:42

线程组ThreadGroup

/*
* 线程组ThreadGroup
*
* 结论:
* 如果在设置线程组优先级之前设置线程优先级,则线程优先级不受线程组优先级限制
* 如果在设置线程组优先级之后设置线程优先级,则线程优先级不能超过线程组优先级
*
* 线程的优先级,默认与启动它的父线程相同,但受到所有线程组的限制
*/

public class Test02 {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "线程,所属线程组:"
+ Thread.currentThread().getThreadGroup());
System.out.println(Thread.currentThread());

Thread.currentThread().setPriority(8);
Thread th=new Thread("mythread");
System.out.println(th.getPriority());


// 定义一个线程组tg
ThreadGroup tg = new ThreadGroup("wbs14061线程组");
System.out.println("tg线程组的父线程组:"+tg.getParent());


//创建线程一,属于tg线程组
Thread th1=new Thread(tg, new MyThread2(), "first");
Thread th2=new Thread(tg, new MyThread2(), "second");

th1.setPriority(8);
tg.setMaxPriority(4);
th2.setPriority(9);

Thread th3=new Thread(tg, new MyThread2(), "third");

System.out.println("tg线程组的信息:"+tg);
th1.start();
th2.start();
th3.start();

//tg.stop();

}

}

class MyThread2 implements Runnable {
int num = 1;

@Override
public void run() {
while (num <= 100) {
System.out.println(Thread.currentThread().getName() + ","
+ Thread.currentThread().getPriority() + "****" + num++);

}
}

}

多线程访问共享数据

/*
* 多线程访问共享数据
*
* 多线程操作共享数据可能会出现问题,即线程安全问题
* 原因:当多个线程操作共享数据时,一个线程只执行了部分语句,还没执行完,此时CPU时间片切换了,另一个线程参与进来,导致共享数据的错误
* 解决:同步机制synchronized
*
* 同步的前提:
* 1.必须要有两个或者两个以上的线程
* 2.必须是多个线程使用同一个锁
*
* 保护范围:
* 1.只将需要的代码添加到synchronized块中
* 2.不要将run()方法中所有的代码都添加到synchronized块中,否则相当于单线程
*
* 线程同步的优缺点:
* 优点:解决了线程安全
* 缺点:由于多个线程需要进行锁的判断,消耗资源,导致效率降低
*/

public class Test03 {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread th1 = new Thread(ticket, "线程1");
Thread th2 = new Thread(ticket, "线程2");
Thread th3 = new Thread(ticket, "线程3");
th1.start();
th2.start();
th3.start();
}
}

class Ticket implements Runnable {
private int num = 100; // 总共100张票,共享此数据
Object obj = new Object();

@Override
public void run() {
while (true) {
// 关键代码块,保护共享数据的安全
synchronized (obj) {
if (num > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "售出车票:" + num--);
}
}
}
}
}

synchronized 方法


/*
* 使用synchronized修改方法,称为同步方法(同步函数),线程安全的
*
* 同步函数使用的锁是当前对象,即this锁
* 静态同步函数使用的锁是字节码文件对象
*/

public class Test04 {
public static void main(String[] args) {
Account account=new Account();
Thread th1=new Thread(account, "你爸");
Thread th2=new Thread(account, "你妈");
th1.start();
th2.start();
}
}

/*
* 银行账户类
*/

class Bank {
private double balance;// 余额

// 查看余额
public void getBalance() {
System.out.println("当前余额:" + balance);
}

// 存钱
public void setBalance(double money) {
balance = balance + money;
}
}

/*
* 两个人同时往一个账户里打钱,每次打300元,总共打3次,合计900元
*/


class Account implements Runnable {
private static Bank bank = new Bank();
static int i = 1;

@Override
public void run() {
while (true) {
saveMoney();
}
}

//同步函数,同一时间只能有一个线程执行此函数
public static synchronized void saveMoney(){
if (i <= 3) {
try {
Thread.sleep(10);//休眠10ms,打钱次数会异常
} catch (InterruptedException e) {
e.printStackTrace();
}
bank.setBalance(300);
System.out.println(Thread.currentThread().getName()
+ "存了300元,第" + (i++) + "次");
bank.getBalance();// 打印当前余额
} else {
System.exit(0);
}
}

}