java21
关于枚举----enum
一个一个列举
public static void main(String[] args) {
// 作为一个类,还是要提供服务--外部能获取到对象
season s = season.spring;
// 用switch--case
switch (s) {//枚举
case spring :
System.out.println("春");
break;
case summer:
System.out.println("夏");
break;
case autumn:
System.out.println("xx");
break;
case winter :
System.out.println("xxxxx");
break;
default:
System.out.println();
break;
}
}
enum season{
// 枚举类的属性-----枚举常量(本质是对象) ----所有的枚举常量一定要在首行
//枚举中的属性与--public final static season spring =new season();等效
spring {
@Override
public void n() {
// TODO Auto-generated method stub
}
},
summer {
@Override
public void n() {
// TODO Auto-generated method stub
}
},
autumn {
@Override
public void n() {
// TODO Auto-generated method stub
}
},
winter {
@Override
public void n() {
// TODO Auto-generated method stub
}
};
// 可以创建普通属性和方法
int i =1;
public void m(){}
// 枚举中的所有构造方法都必须私有化
private season(){}
//也可以定义抽象方法,但是定义抽象方法后,枚举对象必须重写方法,
public abstract void n();
}
}
/*class season{
// 外部获取不到构造方法---外部拿不到对象构建过程
// 构造方法私有化
private season(){}
// 本类可以访问私有化信息--创建本类对象
// 用static修饰,设为静态属性,让外部不创建对象的前提下获取到
// 再用final修饰,固定地址值
// 用public修饰,可以让外部拿到
public final static season spring =new season();
public final static season summer =new season();
public final static season autumn =new season();
public final static season winter =new season();
}*/
--------------––––--–---
关于线程
进程:计算机执行的任务。
进程执行程序的各个任务。
进程是由线程组成,
线程执行进程中的各个任务
计算机在执行过程中,在同一时间只能让cpu的核执行一个进程
进程由多个线程来执行,在同一时刻cpu只能处理一个线程
引入多线程
当线程被cpu执行时,cpu开始工作,线程需要和软件或者
硬件进行交互。在交互时cpu处于空闲状态。
引入多线程后,可以提高cpu使用效率
例如一个线程占用0.1,系统空闲为0.9
则两个线程效率为占用,0.19 空闲为0.81
第一种方法:继承Thread类,重写run方法,
调用start方法,用于开启线程
线程的基本演示
继承Thread缺点,类与类之间只能单继承,会影响其他类
public static void main(String[] args) {
// 执行线程----执行线程代码逻辑所在的类
xiancheng x = new xiancheng();
// 调用父类方法---用于开启线程---Thread类里的方法;
x.start();
// 测试---主逻辑代码
for (int i = 10; i >0; i--) {
System.out.println("main:"+i);
}
}
}
//线程任务执行的的代码逻辑
class xiancheng extends Thread{
// 线程的代码逻辑
// 重写run方法
@Override
public void run(){
for(int i=0;i<=10;i++){
System.out.println(i);
}
}
}
第二种方法:
实现Runnable接口,重写run方法(线程代码逻辑),
通过Runnable接口的实现类兑现构建Thread类对象,调用
start方法开启线程;
常用写法
public static void main(String[] args) {
//通过Runnable实现类对象,构建Thread类对象
Thread t = new Thread(new xiancheng2());
// 开启线程
t.start();
//
for (int i = 0; i <10; i++) {
System.out.println("main"+i);
}
}
}
//线程代码逻辑所在的类----实现Runnable接口
class xiancheng2 implements Runnable{
//重写run方法-----线程代码逻辑
@Override
public void run() {
for (int i = 0; i <10; i++) {
System.out.println(i);
}
}
}
第三种方法
实现Callable接口,重写call方法,现阶段了解即可
import java.lang.reflect.Executable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadDemomo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建一个线程类对象
Th t =new Th();
// 获取执行服务器
ExecutorService e = Executors.newCachedThreadPool();
//提交
Future<Integer> f = e.submit(t);
//获取
System.out.println(f.get());
}
}
class Th implements Callable<Integer>{
//重写方法---线程代码逻辑
@Override
public Integer call() throws Exception {
// TODO Auto-generated method stub
return 10;
}
}
底层多线程之间,存在抢占问题,抢占发生在代码的每一步
导致数据安全问题。
解决方法—保证逐个执行
加锁----同步代码锁、同步方法锁
同步代码锁格式 synchronized ( 锁对象 ){ 代码块 }
锁对象指的是可以被线程共享–方法区里的内容可以被所有线程共享
while(true){
//同步代码锁--一次只允许一个线程进入---小括号内填写锁对象---应被线程共享
//锁住selle整个类应填写 selle.class
//填写Math.class表示锁住所有对象
//t---直接锁共享的对象
//若只有一个对象的时候 括号也可以填写this,this指代当前类的对象每个对象进行单独加锁
synchronized (t) {
if(t.getCount()<=0){break;}
// 票数为0时,结束循环
t.setCount(t.getCount()-1);
// 打印具体是哪个线程执行
System.out.println(Thread.currentThread().getName()
+"卖了一张,还剩"+t.getCount()+"张票。");
}
}
同步方法锁—同步方法锁,锁非静态方法,锁对象默认为this
如果是静态方法,则锁对象是 类名.class
格式 public synchronized void run() {}
关于锁之间的相互嵌套,发生的死锁问题
通过锁的等待–唤醒 机制来解决
用两个学生轮流向老师问问题来演示,A问完老师,轮到B,在轮到A…
public class ThreadLock {
public static void main(String[] args) {
//创建学生类对象
student s =new student();
s.setName("as");
// 开启线程
new Thread(new ask(s)).start();
new Thread(new change(s)).start();
}
}
class ask implements Runnable{
private student s;
public ask(student s ){
this.s=s;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized (s) {
if(s.flag==false)
// 释放线程执行权---等待
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("老师你好,我就过来看看,我是"+s.getName());
s.notify();
s.flag=false;
}
}
}
}
//线程所在类
class change implements Runnable{
//引入学生类
private student s;
public change(student s ){
this.s=s;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
// 等待,释放执行权
synchronized (s) {
if(s.flag==true)
try {
s.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(s.getName().equals("tom")){
s.setName("jack");
}else{
s.setName("tom");
}
// 唤醒线程
s.notify();
//改变布尔值
s.flag=true;
}
}
}
}
//创建一个学生类
class student{
private String name;
boolean flag = true;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
wait与sleep的区别
sleep–如果线程没有加锁,就会释放线程的执行权,如果加锁就不会
释放执行权,可以指定休眠时间,是Thread的静态方法
wait–可以指定等待时间,时间到了也能唤醒,如果不指定时间,
就只能手动唤醒,不管有没有锁,都会释放线程执行权,Object里的
普通方法;
关于线程的状态
守护线程:被守护线程一旦结束,守护线程终止,只要不是守护线程,
就是被守护线程,java中最大的守护线程是GC
守护线程示例
public class DemonDemo {
public static void main(String[] args) {
//创建出小兵对象
Thread t1=new Thread(new Soilder(),"小兵1");
Thread t2=new Thread(new Soilder(),"小兵2");
Thread t3=new Thread(new Soilder(),"小兵3");
Thread t4=new Thread(new Soilder(),"小兵4");
//设置守护线程
t1.setDaemon(true);
t2.setDaemon(true);
t3.setDaemon(true);
t4.setDaemon(true);
//开启线程
t1.start();
t2.start();
t3.start();
t4.start();
//被守护线程
for(int i=10;i>=0;i--){
System.out.println("boss剩余"+i);
}
}
}
//线程类---小兵
class Soilder implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
//输出每个小兵的剩余血量
for(int i=10;i>=0;i--){
System.out.println
(Thread.currentThread().
getName()+"还剩"+i+"滴血...");
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
线程的优先级(1-10)个级别
理论上优先级越大,越有概率抢到执行权
如果线程之间的优先级差值超过了5,才会有些许差别,仅仅作为了解,功能比较鸡肋;