程序、进程、线程
线程的创建
继承Thread类
//todo 继承Thread类
public class Test1 extends Thread{
public static void main(String[] args) throws InterruptedException {
//todo 创建线程对象
Test1 test1 = new Test1();
//todo 调用start对象
test1.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程"+i);
sleep(1);
}
}
@Override
public void run() {
//super.run();
//todo 重写run方法
for (int i = 0; i < 100; i++) {
System.out.println("重写的run方法"+i);
try {
sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
实现Runnable接口
import static java.lang.Thread.sleep;
//todo 实现Runnable接口
public class Test1 implements Runnable{
public static void main(String[] args) throws InterruptedException {
//todo 创建 Runnable接口实现类对象
Test1 test1 = new Test1();
//todo 创建线程对象,通过线程对象来开启我们的线程
new Thread(test1).start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程"+i);
sleep(1);
}
}
@Override
public void run() {
//super.run();
//todo 重写run方法
for (int i = 0; i < 100; i++) {
System.out.println("重写的run方法"+i);
try {
sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
例子(抢票):
//todo 实现Runnable接口
public class Test1 implements Runnable{
public static int tickeNums=10;
public static void main(String[] args) throws InterruptedException {
//创建实现Runnable接口实现类
Test1 test1 = new Test1();
new Thread(test1,"t1").start();
new Thread(test1,"t2").start();
new Thread(test1,"t3").start();
}
@Override
public void run() {
while(true){
if(tickeNums==0){
break;
}
//Thread.currentThread().getName()获取调用这个线程的对象名
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+tickeNums--+"票;");
}
}
}
上述操作带来的问题:发现有数据重复,这就是多个操作针对同一资源所带来得数据混乱即线程不安全;
实现Callable接口
import java.util.concurrent.*;
//todo 实现Callable接口
public class Test1 implements Callable<Boolean> {
public static int tickeNums=10;
public static void main(String[] args) throws ExecutionException, InterruptedException {
Test1 test1 = new Test1();
Test1 test2 = new Test1();
Test1 test3 = new Test1();
//创建执行服务
ExecutorService executorService = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> submit1 = executorService.submit(test1);
Future<Boolean> submit2 = executorService.submit(test2);
Future<Boolean> submit3 = executorService.submit(test3);
//获取结果
Boolean aBoolean1 = submit1.get();
Boolean aBoolean2 = submit2.get();
Boolean aBoolean3 = submit3.get();
System.out.println(aBoolean1+":"+aBoolean2+":"+aBoolean1);
//关闭服务
executorService.shutdownNow();
}
@Override
public Boolean call() {
while(true){
if(tickeNums==0){
break;
}
//Thread.currentThread().getName()获取调用这个线程的对象名
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+tickeNums--+"票;");
}
return true;
}
}
线程状态
public class Test1 implements Runnable {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Test1());
//观察线程状态 new
Thread.State state = thread.getState();
System.out.println(state);
//观察线程状态 runnable
thread.start();
state = thread.getState();
System.out.println(state);
while (state!=Thread.State.TERMINATED) {
Thread.sleep(100);
state = thread.getState();
System.out.println(state);
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行");
}
}
}
常用方法
Thread thread = new Thread();
//更改线程优先级
thread.setPriority(10);
//类方法,在指定的毫秒数内让当前正在执行的线程体休眠
Thread.sleep(10);
//等待该线程终止
thread.join();
//类方法,暂停当前正在执行的线程对象,并执行其他线程
Thread.yield();
//中断线程,不建议使用
thread.interrupt();
//测试线程是否处于活动状态
boolean alive = thread.isAlive();
停止线程flag
线程休眠sleep
礼让线程yield
线程强制执行join
public class Test1 implements Runnable {
public static void main(String[] args) throws InterruptedException {
Test1 test1 = new Test1();
Thread thread = new Thread(test1);
thread.start();
for (int i = 0; i < 1000; i++) {
if (i==500){
thread.join();
}
System.out.println("main执行"+i);
}
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("vip插队"+i);
}
}
}
线程优先级
public class Test1{
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
Test2 test2 = new Test2();
Thread thread1 = new Thread(test2);
Thread thread2 = new Thread(test2);
Thread thread3 = new Thread(test2);
Thread thread4 = new Thread(test2);
//设置线程优先级,要先设置再启动
thread1.start();
thread2.setPriority(5);
thread2.start();
thread3.setPriority(7);
thread3.start();
thread4.setPriority(3);
thread4.start();
}
}
class Test2 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
守护(daemon)线程
public class Test1{
public static void main(String[] args) {
Test2 test2 = new Test2();
Test3 test3 = new Test3();
Thread thread1 = new Thread(test3);
//默认所有的线程都是用户线程
thread1.setDaemon(true);
thread1.start();
Thread thread = new Thread(test2);
thread.start();
}
}
class Test2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("用户线程");
}
System.out.println("用户线程结束");
}
}
class Test3 implements Runnable {
@Override
public void run() {
while(true){
System.out.println("守护线程");
}
}
}
线程同步
同步方法
public class Test1{
public static void main(String[] args) {
Test2 test2 = new Test2();
new Thread(test2,"你").start();
new Thread(test2,"我").start();
new Thread(test2,"他").start();
}
}
class Test2 implements Runnable {
private int num=1000;
boolean flag=true;
@Override
public void run() {
while (flag){
try {
num_();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//加上synchronized
public synchronized void num_() throws InterruptedException {
if (num<=0){
flag=false;
return;
}
//检查并发性
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"获得了数字"+num--);
}
}
同步块
public class Test1{
public static void main(String[] args) {
Test3 test3 = new Test3(1000);
Test2 test2 = new Test2(test3);
Thread you = new Thread(test2, "你");
Thread me = new Thread(test2, "我");
you.start();
me.start();
}
}
class Test2 implements Runnable {
private Test3 test3;
boolean flag=true;
public Test2(Test3 test3) {
this.test3 = test3;
}
@Override
public void run() {
while (flag){
try {
//synchronized默认锁的是this,现在用块锁住test3对象
synchronized (test3){
num_();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void num_() throws InterruptedException {
if (test3.getNum()<=0){
flag=false;
return;
}
//检查并发性
Thread.sleep(100);
test3.setNum(test3.getNum()-1);
System.out.println(Thread.currentThread().getName()+"获得了数字"+test3.getNum( ));
}
}
//存放数字100
class Test3{
private int num;
public Test3(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
CopyOnWriteArrayList(JUC集合)
import java.util.concurrent.CopyOnWriteArrayList;
public class Test1{
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> strings = new CopyOnWriteArrayList<>();
for (int i = 0; i < 100; i++) {
new Thread(()->{
strings.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(100);
System.out.println(strings.size());
}
}
死锁
LOCK(锁)
import java.util.concurrent.locks.ReentrantLock;
public class Test1 implements Runnable{
int num=10;
//定义lock
private final ReentrantLock lock=new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Test1 test1 = new Test1();
Thread thread1 = new Thread(test1);
Thread thread2 = new Thread(test1);
Thread thread3 = new Thread(test1);
thread1.start();
thread2.start();
thread3.start();
}
@Override
public void run() {
while(true){
try {
lock.lock();//加锁
//将会锁的对象放入try中
if(num==0){
break;
}else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+":"+num--);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//释放锁
}
}
}
}
synchronized与lock的对比
线程通信
注意:均是object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IllegalMonitorStateException
管程法
public class TestPC {
public static void main(String[] args) {
SynContainer synContainer = new SynContainer();
Productor productor = new Productor(synContainer);
Consumer consumer = new Consumer(synContainer);
productor.start();
consumer.start();
}
}
//todo 生产者
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);
try {
container.push(new Thing(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//todo 消费者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container){
this.container=container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println("消费:"+container.pop().id);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//todo 产品
class Thing{
int id;//编号
public Thing(int id) {
this.id = id;
}
}
//todo 缓冲区
class SynContainer{
//放产品的容器
Thing[] things=new Thing[10];
//容器计数器
int count=0;
//生产者放入产品
public synchronized void push(Thing thing) throws InterruptedException {
//如果容器满了,等待消费者生产
if(count==things.length){
//通知消费者消费,生产等待
this.wait();
}
//如果没有满,继续生产产品
things[count]=thing;
count++;
//通知消费者消费
this.notifyAll();
}
public synchronized Thing pop() throws InterruptedException {
Thing thing = null;
//判断是否可以消费
if(count==0){
//等待生产者生产,消费者等待
this.wait();
}
//如果可以消费
count--;
thing=things[count];
//通知生产者生产
this.notifyAll();
return thing;
}
}
信号灯法(标志位)
线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPC {
public static void main(String[] args) {
//创建线程池 newFixedThreadPool参数为线程池的大小
ExecutorService executorService = Executors.newFixedThreadPool(10);
//执行
executorService.execute(new Productor());
executorService.execute(new Productor());
executorService.execute(new Productor());
//关闭连接
executorService.shutdown();
}
}
class Productor implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
推荐学习狂神说