进程与线程的关系
-
进程是执行一个程序操作系统会进行分配一个进程,如idea开启就会有一个进程,而进程里面会有很多线程,如酷狗音乐里面有播放器等。
-
假如电脑只有一个cpu,也就是单核,那么多线程只是轮流执行,因为切换时间很快,因而让人无所察觉。
线程有三种实现方式(Thread,Runnable,Callable)
-
Thread方式
-
首先继承Thread
-
重写run()
-
开启线程start()
public class thread1 extends Thread {
-
-
Runnable方式
-
-
重新run()
-
创建Thread线程
-
把Runnable实现的类传入Thread
-
开启start()
public class runable implements Runnable{
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("这是Runnable,正在打印"+i);
}
}
public static void main(String[] args) {
//创建一个runnable类
runable runable = new runable();
//创建一个线程
Thread thread = new Thread(runable);//代理模式
//开启
thread.start();
//主线程main
for (int i = 0; i < 200; i++) {
System.out.println("这是主线程,正在打印"+i);
}
}
} -
小结:
-
Thread不建议使用:避免oop单继承局限性
-
Runnable推荐使用:灵活方便,方便同一个对象被多个线程使用
-
Callable
-
实现Callable接口
-
重写call()
-
创建实例
-
创建线程服务Executors.newFixedThreadPool
-
提交服务submit
-
获取结果get()
-
关闭服务shutdownNow()
import java.util.concurrent.*;
public class callable implements Callable<Boolean> {
public Boolean call() throws Exception {
for (int i = 0; i < 20; i++) {
System.out.println("这是callable,正在打印"+i);
}
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建callable实例
callable callable1 = new callable();
callable callable2 = new callable();
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(2);//开启两个线程
//提交执行
Future<Boolean> submit = ser.submit(callable1);
Future<Boolean> submit1 = ser.submit(callable2);
//获取结果
Boolean aBoolean = submit.get();
Boolean aBoolean1 = submit1.get();
System.out.println(aBoolean+","+aBoolean1);
//关闭服务
ser.shutdownNow();
}
} -
静态代理
-
两个类必须实现同一个接口
-
一个实例传入另外一个实例,并调用实现接口的方法
public class staticProxy {
public static void main(String[] args) {
You you = new You();
//代理you
MarryCompany marryCompany = new MarryCompany(you);
marryCompany.HappyDay();
//Thread也是一个代理,都是会实现implements Runnable
}
}
interface Marry{
void HappyDay();
}
class You implements Marry{
public void HappyDay() {
System.out.println("今天结婚,好开心!!");
}
}
class MarryCompany implements Marry{
private Marry marry;
public MarryCompany(Marry marry){
this.marry = marry;
}
public void HappyDay() {
before();
//调用
marry.HappyDay();
after();
}
private void after() {
System.out.println("结婚后");
}
private void before() {
System.out.println("结婚前");
}
}
lamda表达式
-
必须有一个接口而且只有一个抽象方法
public class lamda {
public static void main(String[] args) {
//匿名函数
my_lamda m = new my_lamda() {
public void happy() {
System.out.println("hello lamda");
}
};
m.happy();
//lamda表达式
m = () -> {
System.out.println("hello lamda2");
};
m.happy();
//简化
m = () -> System.out.println("hello lamda3");
m.happy();
//带有参数
love love = (int a) ->{
System.out.println(a);
};
love.love(520);
//简化
love = (a) -> System.out.println(a);
love.love(521);
//在简化
love = a -> System.out.println(a);
love.love(522);
//带有两个参数
love2 love2 = (int a,int b) ->{
System.out.println(a+","+b);
};
love2.love2(520,521);
//简化
love2 = (a,b)->{System.out.println(a+","+b);};
love2.love2(522,523);
}
}
//函数式
interface my_lamda{
void happy();
}
interface love{
void love(int a);
}
interface love2{
void love2(int a,int b);
}
方法
线程停止
-
stop()方法不建议使用,建议使用线程标志位来停止
public class TestStop {
public static void main(String[] args) {
stop_test st = new stop_test();
Thread thread = new Thread(st);
//开启
thread.start();
//停止
st.stop();
}
}
class stop_test implements Runnable{
private boolean flag = true;
sleep()
-
每一个类都有一个锁,sleep()不会释放锁
import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class TestSleep {
public static void main(String[] args) {
sleep_test st = new sleep_test();
Thread thread = new Thread(st);
thread.start();
}
}
class sleep_test implements Runnable{
yield()
-
当前的线程暂停,但不阻塞,从运行状态到就绪状态,让cpu重新调度。
public class TestYield {
public static void main(String[] args) {
yield_test yt = new yield_test();
Thread thread = new Thread(yt,"a");
Thread thread2 = new Thread(yt,"b");
thread.start();
thread2.start();
}
}
class yield_test implements Runnable{
join()
-
让线程先执行,也就是插队
public class TestJoin {
public static void main(String[] args) {
join_test jt = new join_test();
Thread thread = new Thread(jt,"join");
thread.start();
for (int i = 0; i < 500; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
if(i == 100){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class join_test implements Runnable{
@Override
public void run() {
for (int i = 0; i < 30; i++) {
System.out.println(Thread.currentThread().getName()+":在数"+i);
}
}
}
线程状态
public class ThreadState {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() ->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//创建
Thread.State state = t.getState();
System.out.println(state);
t.start();
//就绪
state = t.getState();
System.out.println(state);
while (state != Thread.State.TERMINATED){ //线程不死亡就监控
state = t.getState();
System.out.println(state);
Thread.sleep(100);
}
}
}
线程的优先级
-
setPriority(),getPriority()的范围为1~10,数字越大优先级越高
public class TestPriority {
public static void main(String[] args) {
Priority_test pt = new Priority_test();
Thread t1 = new Thread(pt,"a");
Thread t2 = new Thread(pt,"b");
Thread t3 = new Thread(pt,"c");
Thread t4 = new Thread(pt,"d");
t1.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.setPriority(Thread.MAX_PRIORITY);
t2.start();
t3.setPriority(3);
t3.start();
t4.setPriority(7);
t4.start();
System.out.println(Thread.currentThread().getPriority());
}
}
class Priority_test implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":线程的级别为"+Thread.currentThread().getPriority());
}
}
守护线程
-
daemon(true)
-
用户线程一旦结束,守护线程就结束。
public class TestDaemon {
public static void main(String[] args) {
NewYou ny = new NewYou();
God god = new God();
Thread t2 = new Thread(god);
t2.setDaemon(true);
t2.start();
Thread t = new Thread(ny);
t.start();
}
}
class NewYou implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("我还活着");
}
}
}
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝守护着你");
}
}
}
线程同步
-
保证了安全性,但是性能降低。
-
同步就是队列和锁
-
sychronized同步方法和同步块
//买票(sychronized)
public class TestSynchronized {
public static void main(String[] args) {
ticket t = new ticket();
Thread thread = new Thread(t,"小明");
Thread thread1 = new Thread(t,"小红");
thread.start();
thread1.start();
}
}
class ticket implements Runnable{
private int tickets = 10;
private boolean flag = true;
@Override
public void run() {
while (flag){
buy();
}
}
private synchronized void buy(){
if(tickets<=0){
flag = false;
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"购买了第"+tickets--+"票");
}
}
//synchronized代码块
//注意要选择锁的资源
//相对与synchronized方法性能好,原因是锁定的资源少,而前者是整个方法
public class bank {
public static void main(String[] args) {
Account a = new Account(2000);
BankAto t1 = new BankAto(a,1000,0);
BankAto t2 = new BankAto(a,800,0);
t1.setName("小明");
t2.setName("小红");
t1.start();
t2.start();
}
}
class Account {
private float money = 0;
public Account(float money){
this.money = money;
}
public float getMoney(){
return money;
}
public void setMoney(float money){
this.money = money;
}
}
class BankAto extends Thread{
private Account account;
private float fetchMoney;
private float myMoney;
public BankAto(Account account,float fetchMoney,float myMoney){
this.account = account;
this.fetchMoney = fetchMoney;
this.myMoney = myMoney;
}
public void run(){
synchronized (account){
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
fetch();
}
}
private void fetch(){
if(this.account.getMoney() < fetchMoney){
System.out.println(Thread.currentThread().getName()+":余额不足");
return;
}
this.account.setMoney(this.account.getMoney() - fetchMoney);
this.myMoney = this.myMoney + fetchMoney;
System.out.println(this.getName()+":手里的钱为"+this.myMoney);
System.out.println("卡里的钱为"+this.account.getMoney());
}
}
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
public class list_synchronized {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 2000; i++) {
//不安全
// new Thread(()->{
// list.add(Thread.currentThread().getName());
// }).start();
//安全
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
//JUC安全的list
CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<String>();
for (int i = 0; i < 2000; i++) {
new Thread(()->{
copyOnWriteArrayList.add(Thread.currentThread().getName());
}).start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(copyOnWriteArrayList.size());
}
}
死锁
-
多个线程需要对方需要的资源
//死锁
public class deathLock {
public static void main(String[] args) {
test_deathLock t = new test_deathLock(0);
test_deathLock t2 = new test_deathLock(1);
t.start();
t2.start();
}
}
class a{
}
class b{
}
class test_deathLock extends Thread{
static a a = new a();
static b b = new b();
private int select1;
public test_deathLock(int select1){
this.select1 = select1;
}
@Override
public void run() {
deathLick();
}
private void deathLick(){
if(select1 == 1){
synchronized (a){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"获取a");
synchronized (b){
System.out.println(this.getName()+"获取b");
}
}
}else {
synchronized (b){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+"获取b");
synchronized (a){
System.out.println(this.getName()+"获取a");
}
}
}
}
}
Lock锁
-
性能比synchronized好,但是synchronized可以用在方法上
import java.util.concurrent.locks.ReentrantLock;
public class testLock {
public static void main(String[] args) {
ticket2 t = new ticket2();
Thread t2 = new Thread(t,"小共");
Thread t3 = new Thread(t,"小红");
t2.start();
t3.start();
}
}
class ticket2 implements Runnable{
private int tickets = 10;
private boolean flag = true;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (flag){
try {
lock.lock();
buy();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public void buy(){
if(tickets <= 0){
flag = false;
return;
}
System.out.println(Thread.currentThread().getName()+"购买了"+tickets--+"票");
}
}
线程协同
-
是关于消费者和生产者之间的通信
-
wait()让线程等待,并让当前线程释放它持有的锁,直到notify()或notifyAll()让线程唤醒并进入就绪状态。
-
wait(long timeout)让线程等待一段时间,并让当前线程释放它持有的锁,直到notify()或notifyAll()或到指定时间让线程唤醒并进入就绪状态。
-
notify()是唤醒单个线程,notifyAll()是唤醒所有线程。
import java.util.ArrayList;
//管程法
//生产者 消费者 产品 缓存
public class TestXieCheng {
public static void main(String[] args) {
cache cache = new cache();
new Productor(cache).start();
new Consumer(cache).start();
}
}
//产品
class Product{
Integer id;
String name;
public Product(Integer id,String name){
this.id = id;
this.name = name;
}
}
//生产者
class Productor extends Thread{
cache cache;
public Productor(cache cache){
this.cache = cache;
}
public void run(){
//生产
for (int i = 0; i < 10; i++) {
cache.push(new Product(i+1,"罐头"));
}
}
}
//消费者
class Consumer extends Thread{
cache cache;
public Consumer(cache cache){
this.cache = cache;
}
public void run(){
for (int i = 0; i < 10; i++) {
//消费
cache.pop();
}
}
}
//缓存
class cache{
//存放产品
Product[] products = new Product[10];
Integer i = 0;
//生产者
public synchronized void push(Product product){
//是否仓库已满
if(i+1 == products.length){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products[i] = product;
System.out.println("生产了第"+product.id+"个"+product.name);
i++;
//告知消费者消费
this.notifyAll();
}
//消费者
public synchronized Product pop(){
//是否仓库为空
if(products.length == 0){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i--;
Product product = products[i];
System.out.println("消费了第"+product.id+"个"+product.name);
//通知生产者生产
this.notifyAll();
return product;
}
}
import java.util.ArrayList;
//信号灯法
public class TestXinHaoDeng {
public static void main(String[] args) {
TV tv = new TV();
new actor(tv).start();
new watcher(tv).start();
}
}
//演员
class actor extends Thread{
TV tv;
public actor(TV tv){
this.tv =tv;
}
public void run(){
for (int i = 0; i < 10; i++) {
if(i%2 == 0){
tv.performance("奥特曼上演了");
}else {
tv.performance("数鸭子");
}
}
}
}
//观众
class watcher extends Thread{
TV tv;
public watcher(TV tv){
this.tv =tv;
}
public void run(){
for (int i = 0; i < 10; i++) {
tv.watch();
}
}
}
//节目
class TV {
String programs;
//true就让演员表演节目
boolean flag = true;
//节目表演
public synchronized void performance(String programs){
if(!flag){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.programs = programs;
System.out.println("演员:表演了"+programs);
this.flag = !this.flag;
//通知观众看
this.notifyAll();
}
//节目观看
public synchronized void watch(){
if(flag){
//等待
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("观众:看了"+programs);
this.flag = !this.flag;
//通知演员表演
this.notifyAll();
}
}
线程池
-
execute()是执行Runnable接口的类,没有返回值,submit()是Callable接口的类,有返回值,但也可以执行Runnable接口的类。
-
优点:
-
提高响应的速度
-
降低资源的消耗
-
便于管理
-
corePoolSize: 核心池大小
-
maximumPoolSize: 最大线程数
-
keepAliveTime: 线程没有任务最大保持多长时间会终止
-
-
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool {
public static void main(String[] args) {
//创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
//execute是Runnable接口的,没有返回值
service.execute(new polltest());
}
//service.submit();这是有返回值,用get()可以获取返回值
//关闭
service.shutdown();
}
}
class polltest implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"测试Pool");
}
}
总结
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class TestCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//Thread
myThread myThread = new myThread();
myThread.start();
//Runnable
Thread thread = new Thread(()->{
System.out.println("Runnable");
});
thread.start();
//Callable
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {