我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了。
今天介绍一下,在java代码层面解决多线程,高并发问题,主要介绍以下3种方式:
以下是未线程安全同步的代码:
class LockTest {
public static void main(String[] args) {
final Outputter1 output = new Outputter1();
//启动新线程1(传承一个多线程环境)
new Thread() {
//覆盖run方法
public void run() {
//新线程1需要执行的业务代码
output.output("zhangsan");
};
}.start();
//启动新线程2
new Thread() {
public void run() {
//新线程2需要执行的代码
output.output("lisi");
};
}.start();
}
}
class Outputter1 {
public void output(String name) {
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
}
}
结果1:
也可能为:
等等不同结果;
通过结果可以看出:当出现多线程、高并发的情况时运行同一段代码时;会出现不同的结果,从而导致线程安全问题。
要解决以下问题有介绍3中方式:
方式一:
通过synchronized同步方法从而解决高并发问题
class LockTest {
public static void main(String[] args) {
final Outputter1 output = new Outputter1();
//启动新线程1(传承一个多线程环境)
new Thread() {
//覆盖run方法
public void run() {
//新线程1需要执行的业务代码
output.output("zhangsan");
};
}.start();
//启动新线程2
new Thread() {
public void run() {
//新线程2需要执行的代码
output.output("lisi");
};
}.start();
}
}
class Outputter1 {
//通过synchronized同步方法
public synchronized void output(String name) {
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
}
}
方式二:
通过synchronized同步代码块从而解决高并发问题
class LockTest {
public static void main(String[] args) {
final Outputter1 output = new Outputter1();
//启动新线程1(传承一个多线程环境)
new Thread() {
//覆盖run方法
public void run() {
//新线程1需要执行的业务代码
output.output("zhangsan");
};
}.start();
//启动新线程2
new Thread() {
public void run() {
//新线程2需要执行的代码
output.output("lisi");
};
}.start();
}
}
class Outputter1 {
public void output(String name) {
//同步代码块
synchronized (this){
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
}
}
}
方式三:
通过java.util.concurrent.locks.Lock来对代码进行上锁,从而解决高并发问题
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LockTest {
public static void main(String[] args) {
final Outputter1 output = new Outputter1();
new Thread() {
public void run() {
output.output("zhangsan");
};
}.start();
new Thread() {
public void run() {
output.output("lisi");
};
}.start();
}
}
class Outputter1 {
private Lock lock = new ReentrantLock();// 锁对象
public void output(String name) {
// TODO 线程输出方法
lock.lock();// 得到锁
try {
for(int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
} finally {
lock.unlock();// 释放锁(一定要手动解锁)
}
}
}
通过以上3种方式只会得到2种结果:
结果一:
结果二:
通过结果可以看到:
当一个线程代码执行时当执行完后才执行下一线程代码,从而从代码层面解决了线程安全问题