多线程实现
重写Thread类的run()方法
代码编写上非常简单,但是相对来能进行的操作就收到了限制。
public class learning extends Thread{
// 传参可以在构造函数里面将一些参数传入进来
static int output = 1;
@Override
public void run(){
whilt(true){
output++;
System.out.println(output);
}
}
}
public static void main(String[] args) throws InterruptedException {
learning test1 = new learning();
learning test2 = new learning();
test1.start();
test2.start();
t1.join();
}
实现Runnable接口,重写run方法
如果想要实现更加多的操作推荐使用这种方法,因为可以利用下面的线程实现共享参数的互斥操作
public class learning implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread());
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new ThreadRunnable());
Thread t2 = new Thread(new ThreadRunnable());
t1.start();
t2.start();
t1.join();
}
实现Callable接口(相比于前面两种能够具有返回值)
public class learning implements Callable<Integer> {
static int output = 1;
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread());
return 11;
}
}
public static void main(String[] args) throws Exception {
FutureTask<String> t1 = new FutureTask<>(new learning());
FutureTask<String> t2 = new FutureTask<>(new learning());
Thread tt1 = new Thread(t1); //放入需要执行的函数,调用的是learning中的call函数
Thread tt2 = new Thread(t2);
tt1.start(); //开始执行线程
tt2.start();
System.out.println(t2.get()); //这个不能放在start前面,因为在线程开始前,并不会有返回值,会出现持续等待的问题,get是阻塞的
tt1.join();
tt2.join();
}
通过线程池创建线程
这部分内容有点多,后续加
线程锁
Synchronized
给共享资源上锁,不需要人为进行acquire和release,只需要将需要同步的代码块、类放到Synchronized中就可以了,对于不同线程访问同一变量的时候Synchronized能够自动进行上锁、解锁操作。从其他文档的反应来看锁的使用频率是非常高的
用法:
public static void main(String[] args) throws Exception {
learning ln = new learning();
Thread t1 = new Thread(ln);
Thread t2 = new Thread(ln);
t1.start();
t2.start();
t2.join();
}
public class learning implements Runnable {
static int output = 1;
@Override
public void run() {
synchronized (this){ // 这里参数表示的时候锁的目标,this表示这个实例对象
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + (output++));
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
ReentrantLock
和Synchronized可以被线程多次重复获取操作,也就是说,如果某个线程对Lock已经进行了上锁操作,那么后续如果在这个线程里面也又进行上锁,那么这个操作就会被允许执行。更形象来说就好像是锁已经在自己这边了,自然就可以继续执行后续的操作了。
在性能上,高并发量情况下ReetrantLock具备更高的执行效率。
在创建ReentrantLock的时候可以选择是否是公平锁,默认为非公平锁,效率更高。
公平锁:谁先提出锁的请求谁就会获得这个锁,也就是说两个线程可以整整意义上的交替获得锁
非公平锁:随机就近原则,在比较长的时间中,锁
public static void main(String[] args) throws Exception {
learning ln = new learning();
learning ln2 = new learning();
Thread t1 = new Thread(ln);
Thread t2 = new Thread(ln2);
t1.start();
t2.start();
t2.join();
}
public class learning implements Runnable {
static int output = 1;
static Lock lock = new ReentrantLock();
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + ":" + (output++));
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
Semaphore
互斥锁,和PV操作一样,可以设置锁的数量,同一线程进行两次acquire()上锁就会消耗掉两个锁,通过release()释放
public static void main(String[] args) throws Exception {
learning ln = new learning();
learning ln2 = new learning();
Thread t1 = new Thread(ln);
Thread t2 = new Thread(ln2);
t1.start();
t2.start();
t2.join();
}
public class learning implements Runnable {
static int output = 1;
static Semaphore se = new Semaphore(1);
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
se.acquire();
System.out.println(Thread.currentThread().getName() + ":" + (output++));
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
se.release();
}
}
}
}
AtomicInteger
因为i++、++i等操作都不具备原子性,在多线程进行操作的时候这样的操作行为会存在比较多的问题,所以通过AtomicInteger对单个变量进行操作。但是问题也在于只能同步一个值
} finally {
se.release();
}
}
}
}
## AtomicInteger
因为`i++`、`++i`等操作都不具备原子性,在多线程进行操作的时候这样的操作行为会存在比较多的问题,所以通过AtomicInteger对单个变量进行操作。但是问题也在于只能同步一个值

被折叠的 条评论
为什么被折叠?



