Java多线程简单梳理

Java多线程

创建线程

继承Thread类

package com.createThread;

import org.junit.Test;

/**
 * 创建线程方法一: 继承Thread类,重写run方法; 
 * 创建对象,调用start()方法即可开启线程;
 * 可以看到"打游戏"和"敲代码"的输出顺序并不完全一致,说明他们两个是同时进行的; 
 * 若只是调用run()方法,则还是一个线程;
 *
 */
public class TestThread1 extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println("打游戏");
		}
	}

	@Test
	public void testThread() {
		Thread thread = new TestThread1();
		thread.start();
		for (int i = 0; i < 20; i++) {
			System.out.println("敲代码");
		}
	}
}

实现Runnable接口

package com.createThread;

import org.junit.Test;

/**
 * 创建线程方法二: 实现Runnable接口,重写run()方法; 
 * 该类作为Thread构造的参数来创建线程; 
 * 调用start()方法启动线程;
 * 为了避免单继承的局限性,推荐使用实现接口的这种方法;
 *
 */
public class TestThread2 implements Runnable {

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			System.out.println("打游戏");
		}
	}

	@Test
	public void startThread() {
		TestThread2 thread = new TestThread2();
		new Thread(thread).start();
		for (int i = 0; i < 20; i++) {
			System.out.println("敲代码");
		}
	}

}

实现Callable接口

package com.createThread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.Test;

/**
 * 创建线程方法三: 实现Callable接口,实现其call方法;
 * juc并发领域使用,call方法可以有返回值; 了解有限,不做探讨;
 *
 */
public class TestThread3 implements Callable<Boolean> {

	@Override
	public Boolean call() throws Exception {
		for (int i = 0; i < 20; i++) {
			System.out.println("打游戏");
		}
		return true;
	}

	@Test
	public void testThread() {
		ExecutorService es = Executors.newFixedThreadPool(1);
		es.submit(new TestThread3());
		for (int i = 0; i < 20; i++) {
			System.out.println("敲代码");
		}
	}

}

状态转换

sleep()方法

package com.state;
/**
 * Thread.sleep()是当前线程进入阻塞状态;
 * 时间片走完后继续执行;
 * junit好像不支持这个,所以就不用junit来测试了;
 *
 */
public class TestBlock implements Runnable{

	@Override
	public void run() {
		for(int i=10;i>0;i--) {
			System.out.println("倒计时:"+i);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		new Thread(new TestBlock()).start();
	}

}

yield()方法

package com.state;
/**
 * Thread.yield()让线程从执行进入就绪,重新等待cpu调度;
 */
public class TestYield {
	public static void main(String[] args) {
		new Thread(()->{
			System.out.println("Thread1 start");
			Thread.yield();
			System.out.println("Thread1 end");
		}).start();
		
		new Thread(()->{
			System.out.println("Thread2 start");
			System.out.println("Thread2 end");
		}).start();
	}
}

join()方法

package com.state;
/**
 * join方法用于插队,执行join()方法的线程会被有限执行;
 * 如以下例子中,在t1线程执行过程中,碰到t2.join();这行代码时,t2会插队,t1被阻塞,等待t2执行完成后t1再执行;
 * join方法写可以写一个参数:毫秒数;表示等待一段时间后要是插队的线程还没执行完就不再继续等待了;
 *
 */
public class TestJoin {
	public static void main(String[] args) {
		new Thread(()->{
			System.out.println("Thread1 start");
			System.out.println("wait Thread2 finish");
			Thread t2 = new Thread(()->{
				System.out.println("Thread2 start");
				System.out.println("Thread2 end");
			});
			t2.start();
			try {
				t2.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("Thread1 end");
		}).start();
	}
}

线程安全

synchronized

package com.synchronize;
/**
 * 多个线程操作同一个对象时可能会出问题,对应方法上加上synchronized 关键字即可;
 *
 */
public class TestSynchronized {
	public static void main(String[] args) {
		Account account = new Account(100);
		new Thread(new TakeMoney(account, 10)).start();
		new Thread(new TakeMoney(account, 20)).start();
		new Thread(new TakeMoney(account, 30)).start();
		new Thread(new TakeMoney(account, 40)).start();
		new Thread(new TakeMoney(account, 50)).start();
	}
}
class TakeMoney implements Runnable {
	private Account a;
	private int money;
	public TakeMoney(Account a,int money) {
		this.a = a;
		this.money = money;
	}
	@Override
	public void run() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		a.getOutMoney2(this.money);
	}
	
}
class Account {
	private int money;
	public Account(int money) {
		this.money = money;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
	/**
	 * synchronized锁的是this对象
	 * @param money
	 */
	public synchronized void getOutMoney(int money) {
		if(this.money < money) {
			System.out.println("余额不足,无法取出");
		}else {
			this.money -= money;
			System.out.println("你已取出"+money+"元,账户余额为"+this.money+"元");
		}
	}
	/**
	 * 同步块的写法,形如synchronized(){}这种类型,()内填一个对象,这个对象就被锁了。
	 * @param money
	 */
	public void getOutMoney2(int money) {
		synchronized (this) {
			if(this.money < money) {
				System.out.println("余额不足,无法取出");
			}else {
				this.money -= money;
				System.out.println("你已取出"+money+"元,账户余额为"+this.money+"元");
			}
		}
	}
}

CopyOnWriteArrayList

package com.synchronize;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class TestList {
	public void testList1() {
		List<String> list = new ArrayList<String>();
		for(int i=0;i<10000;i++) {
			new Thread(()->{
				list.add("aa");
			}).start();
		}
		System.out.println(list.size());
	}
	
	public void testList2() {
		CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
		for(int i=0;i<10000;i++) {
			new Thread(()->{
				list.add("aa");
			}).start();
		}
		System.out.println(list.size());
	}
	public static void main(String[] args) {
		TestList test = new TestList();
		//由此可知ArrayList是线程不安全的;
		test.testList1();
		//CopyOnWriteArrayList是线程安全的;
		test.testList2();
	}
}

其他

生产者消费者问题

package com.productor_consumer;
/**
 * 生产者消费者问题的解决方案
 */

public class ProductorConsumer1 {
	public static void main(String[] args) {
		SynContainer container = new SynContainer();
		new Productor(container).start();
		new Consumer(container).start();
	}
}

//生产者
class Productor extends Thread{
	SynContainer container;
	public Productor(SynContainer container) {
		this.container = container;
	}
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("生产第"+i+"个面包");
			container.push(new Bread(i));
		}
	}
}
//消费者
class Consumer extends Thread{
	SynContainer container;
	public Consumer(SynContainer container) {
		this.container = container;
	}
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("消费第"+container.pop().id+"个面包");;
		}
	}
}

//缓冲区
class SynContainer{
	Bread[] bread = new Bread[10];
	int count = 0;
	//生产
	public synchronized void push(Bread b) {
		//何时不能生产?count==bread.length的时候,此时需要等待,等待消费者的通知
		while(count == bread.length) {
			try {
				this.wait();//wait方法使得线程进入阻塞,等待notify通知,wait时会释放锁
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		bread[count] = b;
		count++;
		this.notifyAll();
	}
	//消费
	public synchronized Bread pop() {
		//何时不能消费?count==0的时候,此时需要等待,等待生产者的通知
		while(count == 0) {
			try {
				this.wait();//wait方法使得线程进入阻塞,等待notify通知,wait时会释放锁
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		count--;
		Bread b = bread[count];
		this.notifyAll();
		return b;
	}
}
//产品
class Bread{
	int id;
	public Bread(int id) {
		this.id = id;
	}
}

内存可见

package com.testvolatile;
/**
 * 用volatile修饰的变量保证了内存可见性,线程对于此变量的写会立刻刷到主存中,保证其他线程获得的是最新的数据。
 * volatile并不能保证原子性;
 *
 */
public class TestVolatile {
	public volatile static int num = 0;
	public static void main(String[] args) {
		new Thread(()->{
			while(num == 0) {
				
			}
		}).start();
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		num = 1;
		
		//按理说1秒之后,num的值改变了,线程会停下来,但是事实上并不会停下来。加上volatile修饰num即可
	}
}

并发下的单例模式

package com.danli;
/**
 * 
 * 懒汉式单例:
 * volatile修饰防止构造时发生指令重排;
 *
 */
public class Danli {
	private volatile static Danli instance;
	private Danli() {
	}
	public static Danli getInstance() {
		if(instance != null) {
			return instance;
		}
		synchronized (Danli.class) {
			if(instance == null) {
				instance = new Danli();
			}
		}
		return instance;
	}
}

定时调度

package com.time;

import java.util.Timer;
import java.util.TimerTask;

public class TestTimer {
	public static void main(String[] args) {
		//时间类
		Timer timer = new Timer();
		//表示1000毫秒后执行这个任务
		timer.schedule(new MyTimeTask(), 1000);
		//表示一秒后执行,2000毫秒后再次执行,永不停止
		timer.schedule(new MyTimeTask(), 1000,2000);
	}
}

/**
 * 任务类,在run方法中写任务内容
 *
 */
class MyTimeTask extends TimerTask{

	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("任务调度一次");
		}
		System.out.println("end------------");
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值