下面详细讲解一下“彻底搞懂Java多线程(二)”的完整攻略。
1. 线程的基本操作
在Java中,线程是通过Thread
类来创建和启动的。创建线程的过程就是创建一个Thread
对象,然后通过调用该对象的start()
方法来启动线程,如下所示:
Thread thread = new Thread();
thread.start();
默认情况下,新线程会与当前线程共享相同的优先级和状态。但是我们可以通过以下方式进行一些设置:
1.1 设置线程名称
可以通过以下方式为线程设置名称:
Thread thread = new Thread();
thread.setName("MyThread");
1.2 设置线程优先级
可以通过以下方式为线程设置优先级:
Thread thread = new Thread();
thread.setPriority(Thread.MAX_PRIORITY); // 设置为最高优先级
1.3 后台线程
可以通过以下方式将线程设置为后台线程:
Thread thread = new Thread();
thread.setDaemon(true);
1.4 通过继承Thread类创建线程
除了创建一个Thread对象之外,还可以通过继承Thread类来创建一个自定义的线程类。只需覆盖Thread类中的run()
方法即可。
public class MyThread extends Thread {
public void run() {
// 线程要执行的代码
}
}
2. 线程同步
在多线程并发执行的过程中,会经常遇到多个线程同时访问共享资源的情况,这时就需要使用线程同步技术,防止多个线程同时修改共享资源造成的数据异常问题。
2.1 synchronized关键字
synchronized
关键字可以用来对代码块或方法进行加锁,保证同一时间只有一个线程可以执行其中的代码。
synchronized (this) {
// 需要同步的代码块
}
或者直接在方法上加上synchronized
关键字:
public synchronized void method() {
// 需要同步的方法体
}
2.2 ReentrantLock类
除了synchronized
关键字之外,ReentrantLock
类也可以用来实现线程同步。这个类具有更强的扩展性和灵活性,并且可以进行可中断锁、公平锁等操作。
// 创建一个可重入锁
ReentrantLock lock = new ReentrantLock();
// 加锁
lock.lock();
try {
// 需要同步的代码块
} finally {
// 解锁
lock.unlock();
}
3. 示例
以下是一个使用synchronized
关键字进行线程同步的示例:
public class MyRunnable implements Runnable {
private int count = 0;
public synchronized void run() {
for (int i = 0; i < 100000; i++) {
count++;
}
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
t1.start();
t2.start();
try {
t1.join(); // 等待t1线程执行完毕
t2.join(); // 等待t2线程执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + mr.getCount());
}
}
以上代码会启动两个线程,它们会对count
变量进行加一操作,共加一十万次。由于没有进行线程同步,可能会导致数据异常问题。在MyRunnable
类的run()
方法上加上synchronized
关键字,可以保证同一时间只有一个线程可以进行加一操作,从而避免了数据异常问题。
以下是一个使用ReentrantLock
类进行线程同步的示例:
public class MyRunnable implements Runnable {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void run() {
lock.lock(); // 加锁
try {
for (int i = 0; i < 100000; i++) {
count++;
}
} finally {
lock.unlock(); // 解锁
}
}
public int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
MyRunnable mr = new MyRunnable();
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);
t1.start();
t2.start();
try {
t1.join(); // 等待t1线程执行完毕
t2.join(); // 等待t2线程执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Count: " + mr.getCount());
}
}
以上代码同样会启动两个线程,它们会对count
变量进行加一操作,共加一十万次。使用ReentrantLock
类进行线程同步可以保证同一时间只有一个线程可以进行加一操作,从而避免了数据异常问题。同时,使用try…finally
代码块可以保证在任何情况下都会释放锁,避免出现死锁问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:彻底搞懂Java多线程(二) - Python技术站