// 自定义个线程类,继承thread类
public class TestThread extends Thread{
public static void main(String[] args) {
// 实例化线程对象,调用start方法启动
TestThread th = new TestThread();
th.start();
for (int i = 0; i < 1000; i++) {
System.out.println("主线程"+i);
}
}
// 重写run方法(IDEA中按住ALT+INSERT键,点击Override Method,快速生成run方法)
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("子线程"+i);
}
}
}
public class TestRunnable implements Runnable {
public static void main(String[] args) {
TestRunnable tr = new TestRunnable();
new Thread(tr).start();
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"主线程"+i);
}
}
public void run() {
for (int i = 0; i < 100; i++) {、
System.out.println(Thread.currentThread().getName()+"子线程"+i);
}
}
}
// 可以直接加载方法上,此时锁的对象是方法指向的this
public synchronized void xxx(){
}
// 也可以写同步块
synchronized(object){
xxx
}
保证多个线程永远获取变量的最新值,让变量成为各个线程之间的共享变量,即线程1修改变量后,其他变量可以感知到变量变化。和synchronized关键字的区别:(参考博客:点击链接)
synchronized(this){
xxx
}
ReentrantLock rtl = new ReentrantLock();
try{
rtl.lock();
xxx
}finally {
// 一般有异常,在finally中解锁
rtl.unlock();
}
两个锁的方式进行对比:
JAVA中线程间的通信模型大致分为两类:共享内存和消息传递。
JAVA线程之间通信的几种方法,只能在同步方法或者同步代码块中调用,否则会抛出异常:
协作方式 | 加synchronized关键字 | 先唤醒后挂起 |
---|---|---|
suspend/resume | 死锁 | 死锁 |
wait/notify,notifyAll | 不会死锁 | 死锁 |
park/unpark | 死锁 | 不会死锁 |
CountDownLatch.await()
进行线程等待,直到N变为0,线程就会被唤起自动执行,而其他线程就可以进行业务判断并用CountDownLatch.countDown()
把N进行线程安全自减,直到触发await的线程。import sun.misc.Cache;
import java.beans.Customizer;
public class ThreadCommumucate {
public static void main(String[] args) {
CacheContainer cacheContainer = new CacheContainer();
new Cusomter(cacheContainer).start();
new Provider(cacheContainer).start();
}
}
// 消费者
class Cusomter extends Thread{
CacheContainer cacheContainer;
public Cusomter(CacheContainer cacheContainer) {
this.cacheContainer = cacheContainer;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("购买到的产品:"+cacheContainer.buy().id);
}
}
}
// 生产者
class Provider extends Thread{
CacheContainer cacheContainer;
public Provider(CacheContainer cacheContainer) {
this.cacheContainer = cacheContainer;
}
@Override
public void run() {
for (int i = 0; i < 50; i++) {
cacheContainer.build(new Product(i));
System.out.println("生产的产品:"+i);
}
}
}
// 产品
class Product{
int id;
public Product(int id){
this.id = id;
}
}
// 缓冲池
class CacheContainer{
Product[] products = new Product[10];
int count = 0;
// 生产产品
public synchronized void build(Product p){
// 如果产品池达到了设置的最大值10,就让线程进行等待
if(count==products.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生产产品并且放进产品池
products[count] = p;
count++;
// 通知所有消费者消费
this.notifyAll();
}
// 消费产品
public synchronized Product buy(){
// 如果没有产品就等待
if(count == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 从池子中拿走产品
count--;
Product p = products[count];
// 通知生产者继续生产
this.notifyAll();
return p;
}
}
public class SignoLight {
public static void main(String[] args) {
Crossroad crossroad = new Crossroad();
new NorthRoad(crossroad).start();
new EastRoad(crossroad).start();
}
}
// 南北方向道路
class NorthRoad extends Thread{
Crossroad crossroad;
public NorthRoad(Crossroad crossroad){
this.crossroad = crossroad;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
this.crossroad.northRun();
}
}
}
// 东西方向道路
class EastRoad extends Thread{
Crossroad crossroad;
public EastRoad(Crossroad crossroad){
this.crossroad = crossroad;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
this.crossroad.eastRun();
}
}
}
// 十字路口
class Crossroad{
// 标志位
// 为true时,南北放行,为false时,东西放行
boolean flag = true;
public synchronized void northRun(){
// 如果为false,等待
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 否则放行300ms,并通知其他线程执行
System.out.println("南北放行300ms");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = !flag;
this.notifyAll();
}
public synchronized void eastRun(){
// 如果为true,等待
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 否则放行300ms,并通知其他线程执行
System.out.println("东西放行300ms");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = !flag;
this.notifyAll();
}
}
// 输出结果为(南北和东西交替):
南北放行300ms
东西放行300ms
南北放行300ms
东西放行300ms
南北放行300ms
东西放行300ms
...
线程经常会被创建、销毁,在这个过程中会使用较多的资源,如果在并发量很高的情况下,会对系统性能造成很大的影响。基于性能考虑和资源利用的考虑,建立线程池对线程进行统一的管理,使用线程池的好处: