目录
一、多线程的优缺点
优点:
提高程序的响应,提高CPU的利用率,改善程序结构
缺点:
线程占用内存,占用CPU资源高,需要对多线程进行管理
多线程同时对共享资源进行访问,如果不加以控制,会出现安全线程问题。
二、线程同步
并行:是真正意义上的同时执行,一个时间节点上有多个任务同时执行。
并发:在同一个时间段内,多个任务依次执行
多线程在共享同一个资源时有可能导致安全问题,我们的解决方案就是引入线程同步机制,即各线程之间要先来后到,确保一个时间点只有一个线程访问共享资源。可以给共享资源加一把锁,哪个线程获取了这把锁,才有权利访问该共享资源
三、锁
1.synchronized关键字
可以解决线程安全问题,具体做法如下:
同步代码块:syncnized(同步锁){ }
修饰代码块时必须传入一个被多个线程所共有的对象,
如果使用继承Thread的方法启动线程,那么就要new一个静态的object(也可以是其他对象)对象,如果是实现Runnable接口就只需用this即可,具体方法如下:
窗口一和窗口二同时取票,总共有10张
public class Run implements Runnable{
int num=10;
@Override
public void run() {
while(true){
print();
if(num<=0)
break;
}
}
public synchronized void print(){
if(num>0){
System.out.println(Thread.currentThread().getName()+num);
num--;
}
}
}
public class Test {
public static void main(String[] args) {
Run run = new Run();
Thread thread1 = new Thread(run,"窗口一");
thread1.start();
Thread thread2 = new Thread(run,"窗口二");
thread2.start();
}
}
运行结果:
窗口一10
窗口一9
窗口一8
窗口一7
窗口二6
窗口二5
窗口二4
窗口二3
窗口二2
窗口二1
窗口一 和窗口二同时取票,没有出现重复取票问题。
2.同步方法:syncnized修饰一个方法
(1)在继承Thread类时,synchronized修饰静态方法默认是Class类的对象
(2)在继承Thread类时,synchronized饰普通方法默认是this,所以在这种创建线程时应当将方法设置为静态方法
(3)在实现Runnable接口时,因为创建的线程任务对象只有一个本身就是同一个对象,所以修饰方法时直接使用synchronized即可
public class Run1 extends Thread{
static int num=1000;
public void run(){
while(true){
if(num<=0){
break;
}
else {
try {
print();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static synchronized void print() throws InterruptedException {
if(num>0){
Thread.currentThread().sleep(1000);
System.out.println(Thread.currentThread().getName()+num);
num--;
}
}
}
public class Test1 {
public static void main(String[] args) {
Run1 run1 = new Run1();
Run1 run2 = new Run1();
run1.setName("窗口一");
run2.setName("窗口二");
run1.start();
run2.start();
}
}
窗口一10
窗口一9
窗口一8
窗口一7
窗口二6
窗口二5
窗口二4
窗口二3
窗口二2
窗口二1
2.Lock锁
public class Run implements Runnable{
int num=10;
ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while(true){
try{
lock.lock();
if (num > 0) {
System.out.println(Thread.currentThread().getName() + num);
num--;
} else
break;
}finally{
lock.unlock();}
}
}
}
public class Test {
public static void main(String[] args) {
Run run = new Run();
Thread thread=new Thread(run,"窗口一");
Thread thread2=new Thread(run,"窗口二");
thread.start();
thread2.start();
}
}
窗口一10
窗口一9
窗口一8
窗口一7
窗口二6
窗口二5
窗口二4
窗口二3
窗口二2
窗口二1