多线程学习Day07

news2024/12/22 15:00:46

共享模型之不可变

从一个日期转换的问题开始

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    log.debug("{}", sdf.parse("1951-04-21"));
                } catch (Exception e) {
                    log.error("{}", e);
                }
            }).start();
        }
    }
}

这里出现了异常

java.lang.NumberFormatException: For input string: "4E14"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Long.parseLong(Long.java:692)
	at java.base/java.lang.Long.parseLong(Long.java:817)
	at java.base/java.text.DigitList.getLong(DigitList.java:195)
	at java.base/java.text.DecimalFormat.parse(DecimalFormat.java:2121)
	at java.base/java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1933)
	at java.base/java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1541)
	at java.base/java.text.DateFormat.parse(DateFormat.java:393)
	at n7.Test1.lambda$main$0(Test1.java:14)
	at java.base/java.lang.Thread.run(Thread.java:829)

加锁当然能解决这个问题

 synchronized (sdf){
                   try {
                       log.debug("{}", sdf.parse("1951-04-21"));
                   } catch (Exception e) {
                       log.error("{}", e);
                   }
               }

换一个不可变类

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        DateTimeFormatter stf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {

                TemporalAccessor parse = stf.parse("1951-04-21");
                log.debug("{}",parse);
            }).start();
        }
    }
}

不可变类的设计

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
// ...
}
北

比如String这个类,他的两个成员变量,一个value[]使用final修饰,一个hash是私有的并且没有get方法,类也加上了fianl修饰,防止子类对其有影响,属性用 final 修饰保证了该属性是只读的,不能修改,类用 final 修饰保证了该类中的方法不能被覆盖,防止子类无意间破坏不可变性


保护性拷贝

public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

发现其内部是调用 String 的构造方法创建了一个新字符串,再进入这个构造看看,是否对 final char[] value 做出了修改:

public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}

享元模式

 定义 英文名称:Flyweight pattern. 当需要重用数量有限的同一类对象时

在JDK中 Boolean,Byte,Short,Integer,Long,Character 等包装类提供了 valueOf 方法,例如 Long 的valueOf 会缓存 -128~127 之间的 Long 对象,在这个范围之间会重用对象,大于这个范围,才会新建 Long 对象:

public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}

Byte, Short, Long 缓存的范围都是 -128~127
Character 缓存的范围是 0~127
Integer的默认范围是 -128~127
             最小值不能变
             但最大值可以通过调整虚拟机参数 `
             -Djava.lang.Integer.IntegerCache.high` 来改变
Boolean 缓存了 TRUE 和 FALSE

例如:一个线上商城应用,QPS 达到数千,如果每次都重新创建和关闭数据库连接,性能会受到极大影响。 这时预先创建好一批连接,放入连接池。一次请求到达后,从连接池获取连接,使用完毕后再还回连接池,这样既节约了连接的创建和关闭时间,也实现了连接的重用,不至于让庞大的连接数压垮数据库。

一个小的连接池例子:

public class Test2 {
    public static void main(String[] args) {
        Pool  pool=new Pool(2);
        for (int i=0;i<5;i++){
            new Thread(()->{
                Connection conn=pool.borrow();
                 try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                pool.free(conn);
            }).start();
        }
    }
}
@Slf4j(topic = "c.Pool")
class Pool{
    //1.连接池大小
    private final int poolSize;
    //2.连接对象数组
    private Connection[] connections;
    //3.连接状态数组,0表示空闲,1表示繁忙
    private AtomicIntegerArray states;
    //4.构造方法
    public Pool(int poolSize){
        this.poolSize=poolSize;
        this.connections=new Connection[poolSize];
        this.states=new AtomicIntegerArray(new int[poolSize]);
        for(int i=0;i<poolSize;i++){
            connections[i]=new MockConnection("连接"+i);
        }
    }

    //借连接
    public Connection borrow()  {
        while (true){
            for (int i=0;i<poolSize;i++){
                if(states.get(i)==0){
                    log.debug("成功进入");
                    if(states.compareAndSet(i,0,1)){
                        log.debug("borrow{}",connections[i]);
                        return connections[i];
                    }
                }
            }
            //没有空闲连接进入等待
            synchronized (this){
                try {
                    log.debug("wait...");
                    this.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            }
        }
    //归还连接
    public void free(Connection conn){
        for (int i=0;i<poolSize;i++){
            if(connections[i]==conn){
                states.set(i,0);
                log.debug("free{}",conn);
                synchronized (this){
                    this.notifyAll();
                }
                break;
            }
        }
    }
}

final原理

设置 final 变量的原理
public class TestFinal {
final int a = 20;
}

字节码 

0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 20
7: putfield #2 // Field a:I
<-- 写屏障
10: return
获取final变量的原理
1. 编译时的行为
  • 编译期常量:如果一个final变量在声明时就被显式初始化(例如,基本类型或字符串字面量),并且它是静态的(static),那么它会被视为编译期常量。Java编译器会将这些常量的值嵌入到任何使用它们的代码中。这意味着,如果这些final常量的值在编译时是已知的,则它们的使用可以在编译时被直接替换为实际的值。

  • 非编译期常量:对于非静态的final变量,或者其值在运行时才能确定的final变量(例如,通过方法计算得到的值),则它们不是编译期常量。这些变量的值存储在类的实例中(非静态)或类本身(静态但非常量)。

2. 运行时的行为
  • 内存模型和可见性final字段的最大特点之一在于它们对内存模型的影响。在Java内存模型中,正确构造的对象(在对象的构造函数完成后,final字段的值就不再改变)中的final字段,可以保证被不同线程安全地读取,无需额外的同步措施。这种行为是通过在构造器结束时对final字段的写入,以及每次读取final字段时都建立的“初始化安全性”保证来实现的。

  • 构造器内的赋值:Java允许在构造器内部对final变量进行赋值。一旦构造器完成,final变量的值就固定下来,任何尝试修改final变量的操作都将导致编译错误。

共享模型之工具

线程池

自定义线程池

终于成功了

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        ThreadPool threadPool= new ThreadPool(2,1000,TimeUnit.MILLISECONDS,10);
        for (int i=0;i<5;i++){
            int j=i;
            threadPool.excute(()->{
                log.debug("{}",j);
            });
        }
    }
}
@Slf4j(topic = "c.ThreadPool")
class ThreadPool{
    //任务队列
    private BlockingQueue<Runnable> taskQueue;
    //线程集合
    private HashSet<Worker> workers=new HashSet();
    //核心线程数
    private int coreSize;
    //获取任务的超时时间
    private long timeout;
    private TimeUnit timeUnit;
    //执行任务
    public void excute(Runnable task){
        //当任务数没有超过coreSize时,交给worker对象执行,如果超过了,加入任务队列暂存
        synchronized (workers){
            if(workers.size()<coreSize){

                Worker worker=new Worker(task);
                log.debug("新增worker {},{}",worker,task);
                workers.add(worker);
                worker.start();
            }else {
                log.debug("加入任务队列 {}",task);
                taskQueue.put(task);
            }
        }
    }

    public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit,int queueCapCIty) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.taskQueue=new BlockingQueue<>(queueCapCIty);
    }
    class Worker extends Thread{
        private Runnable task;

        public Worker( Runnable task) {
            this.task = task;
        }
        @Override
        public void run(){
            //执行任务1.当task不为空,直接执行任务2.当task执行完毕,接着从任务队列获取任务并执行
            while (task!=null||(task=taskQueue.take())!=null){
                try {
                    log.debug("正在执行...{}",task);
                    task.run();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    task=null;
                }
            }
            synchronized (workers){
                log.debug("worker被移除{}",this);
                workers.remove(this);
            }
        }
    }
}

class BlockingQueue<T>{
    //1.任务队列
    private Deque<T> queue=new ArrayDeque<>();
    //2.锁
    private ReentrantLock lock=new ReentrantLock();
    //3.生产者条件变量
    private Condition fullWaitSet=lock.newCondition();
    //4.消费者条件变量
    private Condition emptyWaitSet=lock.newCondition();
    //5.容量
    private int capcity;

    public BlockingQueue(int capacity) {
        this.capcity=capacity;
    }

    //带超时的阻塞获取
    public T poll(long timeout, TimeUnit unit){
        lock.lock();
        try {
            //将超时时间转化为纳秒
            long nanos=unit.toNanos(timeout);
            while (queue.isEmpty()){
                try {
                    //返回的是剩余时间
                    if(nanos<=0){
                        return null;
                    }
                   nanos= emptyWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t=queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }
    }
    //阻塞获取
    public T take(){
        lock.lock();
        try {
            while (queue.isEmpty()){
                try {
                    emptyWaitSet.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t=queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }
    }
    //阻塞添加
    public void put(T element){
        lock.lock();
        try {
            while (queue.size()==capcity){
                try {
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            queue.addLast(element);
            //放完了之后唤醒一下等着队列元素的线程
            emptyWaitSet.signal();
        }finally {
            lock.unlock();
        }
    }
    //获取大小
    public int size(){
        lock.lock();
        try {
            return capcity;
        }finally {
            lock.unlock();
        }
    }
}
17:16:48 [main] c.ThreadPool - 新增worker Thread[Thread-0,5,main],n8.Test1$$Lambda$30/0x00000008000d5440@77167fb7
17:16:48 [main] c.ThreadPool - 新增worker Thread[Thread-1,5,main],n8.Test1$$Lambda$30/0x00000008000d5440@3c9d0b9d
17:16:48 [main] c.ThreadPool - 加入任务队列 n8.Test1$$Lambda$30/0x00000008000d5440@2f112965
17:16:48 [Thread-0] c.ThreadPool - 正在执行...n8.Test1$$Lambda$30/0x00000008000d5440@77167fb7
17:16:48 [main] c.ThreadPool - 加入任务队列 n8.Test1$$Lambda$30/0x00000008000d5440@1a04f701
17:16:48 [main] c.ThreadPool - 加入任务队列 n8.Test1$$Lambda$30/0x00000008000d5440@4e91d63f
17:16:48 [Thread-1] c.ThreadPool - 正在执行...n8.Test1$$Lambda$30/0x00000008000d5440@3c9d0b9d
17:16:48 [Thread-0] c.Test1 - 0
17:16:48 [Thread-1] c.Test1 - 1
17:16:48 [Thread-1] c.ThreadPool - 正在执行...n8.Test1$$Lambda$30/0x00000008000d5440@1a04f701
17:16:48 [Thread-0] c.ThreadPool - 正在执行...n8.Test1$$Lambda$30/0x00000008000d5440@2f112965
17:16:48 [Thread-1] c.Test1 - 3
17:16:48 [Thread-0] c.Test1 - 2
17:16:48 [Thread-1] c.ThreadPool - 正在执行...n8.Test1$$Lambda$30/0x00000008000d5440@4e91d63f
17:16:48 [Thread-1] c.Test1 - 4

下面这个加了拒绝策略

@Slf4j(topic = "c.Test1")
public class Test1 {
    public static void main(String[] args) {
        ThreadPool threadPool= new ThreadPool(1,1000,TimeUnit.MILLISECONDS,1,(queue,task)->{
            //1.死等
            //queue.put(task);
            //2.带超时等待
            //queue.offer(task,500,TimeUnit.MILLISECONDS);
            //3.让调用者放弃执行
            //log.debug("放弃",task);
            //4.抛出异常
            //throw new RuntimeException("任务执行失败"+task);
            //5.让调用者自己执行任务
            task.run();
        });
        for (int i=0;i<3;i++){
            int j=i;
            threadPool.excute(()->{
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                log.debug("{}",j);
            });
        }
    }
}
@FunctionalInterface//拒绝策略
interface RejectPolicy<T>{
    void reject(BlockingQueue queue,T task);
}
@Slf4j(topic = "c.ThreadPool")
class ThreadPool{
    //任务队列
    private BlockingQueue<Runnable> taskQueue;
    //线程集合
    private HashSet<Worker> workers=new HashSet();
    //核心线程数
    private int coreSize;
    //获取任务的超时时间
    private long timeout;
    private TimeUnit timeUnit;
    private RejectPolicy<Runnable>rejectPolicy;
    //执行任务
    public void excute(Runnable task){
        //当任务数没有超过coreSize时,交给worker对象执行,如果超过了,加入任务队列暂存
        synchronized (workers){
            if(workers.size()<coreSize){

                Worker worker=new Worker(task);
                log.debug("新增worker {},{}",worker,task);
                workers.add(worker);
                worker.start();
            }else {
                log.debug("加入任务队列 {}",task);
                taskQueue.put(task);
                /*
                * 1.死等
                * 2..带超时等待
                * 3.放弃执行
                * 4.抛出异常
                * */
                taskQueue.tryPut(rejectPolicy,task);
            }
        }
    }

    public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit,int queueCapCIty,RejectPolicy<Runnable> rejectPolicy) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.taskQueue=new BlockingQueue<>(queueCapCIty);
        this.rejectPolicy=rejectPolicy;
    }
    class Worker extends Thread{
        private Runnable task;

        public Worker( Runnable task) {
            this.task = task;
        }
        @Override
        public void run(){
            //执行任务1.当task不为空,直接执行任务2.当task执行完毕,接着从任务队列获取任务并执行
            while (task!=null||(task=taskQueue.poll(timeout,timeUnit))!=null){
                try {
                    log.debug("正在执行...{}",task);
                    task.run();
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    task=null;
                }
            }
            synchronized (workers){
                log.debug("worker被移除{}",this);
                workers.remove(this);
            }
        }
    }
}
@Slf4j(topic = "c.BlockingQueue")
class BlockingQueue<T>{
    //1.任务队列
    private Deque<T> queue=new ArrayDeque<>();
    //2.锁
    private ReentrantLock lock=new ReentrantLock();
    //3.生产者条件变量
    private Condition fullWaitSet=lock.newCondition();
    //4.消费者条件变量
    private Condition emptyWaitSet=lock.newCondition();
    //5.容量
    private int capcity;

    public BlockingQueue(int capacity) {
        this.capcity=capacity;
    }

    //带超时的阻塞获取
    public T poll(long timeout, TimeUnit unit){
        lock.lock();
        try {
            //将超时时间转化为纳秒
            long nanos=unit.toNanos(timeout);
            while (queue.isEmpty()){
                try {
                    //返回的是剩余时间
                    if(nanos<=0){
                        return null;
                    }
                   nanos= emptyWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t=queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }
    }
    //阻塞获取
    public T take(){
        lock.lock();
        try {
            while (queue.isEmpty()){
                try {
                    emptyWaitSet.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            T t=queue.removeFirst();
            fullWaitSet.signal();
            return t;
        }finally {
            lock.unlock();
        }
    }
    //阻塞添加
    public void put(T element){
        lock.lock();
        try {
            while (queue.size()==capcity){
                try {
                    log.debug("等待加入任务队列{}...",element);
                    fullWaitSet.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            log.debug("加入任务队列{}",element);
            queue.addLast(element);
            //放完了之后唤醒一下等着队列元素的线程
            emptyWaitSet.signal();
        }finally {
            lock.unlock();
        }
    }
    //带超时时间的阻塞添加
    public boolean offer(T task,long timeout,TimeUnit timeUnit){
        lock.lock();
        try {
            long nanos=timeUnit.toNanos(timeout);
            while (queue.size()==capcity){
                try {
                    log.debug("等待加入任务队列{}...",task);
                    if(nanos<=0){
                        return false;
                    }
                   nanos= fullWaitSet.awaitNanos(nanos);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            log.debug("加入任务队列{}",task);
            queue.addLast(task);
            //放完了之后唤醒一下等着队列元素的线程
            emptyWaitSet.signal();
            return true;
        }finally {
            lock.unlock();
        }
    }
    //获取大小
    public int size(){
        lock.lock();
        try {
            return capcity;
        }finally {
            lock.unlock();
        }
    }

    public void tryPut(RejectPolicy<T> rejectPolicy,T task){
        lock.lock();
        try {
            if(queue.size()==capcity){
                rejectPolicy.reject(this,task);
            }else {
                log.debug("加入任务队列{}",task);
                queue.addLast(task);
                emptyWaitSet.signal();
            }
        }finally {
            lock.unlock();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1658318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20K薪资要什么水平?来看看25岁测试工程师的面试过程…_测试工程师薪资20k(2)

既有适合小白学习的零基础资料&#xff0c;也有适合3年以上经验的小伙伴深入学习提升的进阶课程&#xff0c;涵盖了95%以上软件测试知识点&#xff0c;真正体系化&#xff01; 由于文件比较多&#xff0c;这里只是将部分目录截图出来&#xff0c;全套包含大厂面经、学习笔记、…

无监督式学习

1.是什么&#xff1f; 无监督式学习与监督式学习**最大的区别就是&#xff1a;**没有事先给定的训练实例&#xff0c;它是自动对输入的示例进行分类或者分群&#xff1b; 优点&#xff1a;不需要标签数据&#xff0c;极大程度上扩大了我们的数据样本&#xff0c;其次不受监督信…

华为云CodeArts API专场直播来袭!——探索API全生命周期管理新趋势

API的全生命周期管理是否让你摸不清头脑&#xff1f;你是否对API的前沿技术和应用充满了好奇&#xff0c;渴望一探究竟&#xff1f; 华为云PaaS服务即将在5月10日16:00&#xff0c;为你带来一场别开生面的CodeArts API专场直播活动&#xff01; 你可以在轻松愉快的氛围中&…

Python网络编程 03 实验:FTP详解

文章目录 一、小实验FTP程序需求二、项目文件架构三、服务端1、conf/settings.py2、conf/accounts.cgf3、conf/STATUS_CODE.py4、启动文件 bin/ftp_server.py5、core/main.py6、core/server.py 四、客户端1、conf/STATUS_CODE.py2、bin/ftp_client.py 五、在终端操作示例 一、小…

【CTF-Crypto】RSA-选择明密文攻击 一文通

RSA&#xff1a;选择明密文攻击 关于选择明/密文攻击&#xff0c;其实这一般是打一套组合拳的&#xff0c;在网上找到了利用的思路&#xff0c;感觉下面这个题目是真正将这个问题实现了&#xff0c;所以还是非常棒的一道题&#xff0c;下面先了解一下该知识点&#xff1a;(来自…

Telegram Premium会员有什么功能?

Telegram Premium 是 Telegram 的付费版本&#xff0c;现已上线。付费版本被定位为帮助运行平台并进一步开发它的一种方式。但除此之外&#xff0c;它对你有什么好处&#xff1f;以下是Telegram Premium中包含的八个主要功能&#xff1a; 1.没有广告。 Telegram Premium是无广…

李飞飞团队 AI4S 最新洞察:16 项创新技术汇总,覆盖生物/材料/医疗/问诊……

不久前&#xff0c;斯坦福大学 Human-Center Artificial Intelligence (HAI) 研究中心重磅发布了《2024年人工智能指数报告》。 作为斯坦福 HAI 的第七部力作&#xff0c;这份报告长达 502 页&#xff0c;全面追踪了 2023 年全球人工智能的发展趋势。相比往年&#xff0c;扩大了…

[Linux]如何在Ubuntu 22.04系統安裝Node-red?

Node-red是一個建立在Node.js上的視覺化程式設計工具&#xff0c;其常見的應用情境為建置或轉換各項硬體之間的通信協定的物聯網或工聯網場域&#xff0c;其可藉由設置來安裝第三方應用模組來建置多樣的通信協定節點&#xff0c;包含modbus in/out, mqtt in/out, websocket in/…

Java数组创建与使用

一.创建和初始化 1.数组是怎么创建的&#xff1f; 直接举例子&#xff1a; int[] arr new int[10]; 这里只简单的举一个int开辟数组的例子。 可见java数组的创建于C语言是不同的。前面是一个int[ ]就是一个数组的数据类型&#xff0c;后面的arr是数组名&#xff0c;最后[…

【代码随想录——栈与队列】

1.栈和队列理论基础 栈和队列的原理大家应该很熟悉了&#xff0c;队列是先进先出&#xff0c;栈是先进后出。 2.用栈实现队列 type MyQueue struct {head []intheadSize intstore []intstoreSize int }func Constructor() MyQueue {return MyQueue{head : make([]int,100),h…

《ESP8266通信指南》11-Lua开发环境配置

往期 《ESP8266通信指南》10-MQTT通信&#xff08;Arduino开发&#xff09;-CSDN博客 《ESP8266通信指南》9-TCP通信&#xff08;Arudino开发&#xff09;-CSDN博客 《ESP8266通信指南》8-连接WIFI&#xff08;Arduino开发&#xff09;&#xff08;非常简单&#xff09;-CSD…

qt for android 无法进入调试c++代码解决方法

1.上一篇文章介绍了qt 5.15.13配合NDK25 的解决方法&#xff0c;但是还存在一个问题是可以调试qml代码但是无法进入c代码中。 在网上进行搜索&#xff0c;得到的答案是确实存在这个问题&#xff0c;包括这个qt6版本。 2.看来这个问题没有办法了&#xff0c;静下来思考下。这个…

AI助力临沂商贸的世界语言

“你好”“Bonjour”“Hola”……“中国老板娘”能够流利运用 17 种语言&#xff0c;近日在海外爆火。借由 AI 技术的助力&#xff0c;商家在镜头前自如切换各国语言&#xff0c;与来自全球各地的外商实现无障碍的沟通交流。这种现象背后&#xff0c;是 AI 技术对传统商贸模式的…

Python 控制 Keysight (原Agilent) 直流电源

前言 直流电源是如图型号,是keysight 6631系列;由于本身直流电源的功能也不复杂,所以控制起来相对比较简单,本来不想写这篇文章的,但是想想还是做一个简单的记录吧! 硬件环境结构图: 通信方式:由于该直流电源只GPIB接口,所以是通过GPIB线与设备进行通信 实现原理: …

中国网安上市公司2023财报摘要及启示

随着国内网络安全市场越来越来越来越卷&#xff0c;出海&#xff0c;从原来的陌生遥远不看好&#xff0c;已经成为许多厂商不得不思考的一个新方向。 阻力不变。 地缘政治问题依然存在&#xff0c;沟通成本高&#xff0c;对产品成熟度要求高&#xff0c;对团队背景和公司整体能…

如何通过OMS加快大表迁移至OceanBase

OMS&#xff0c;是OceanBase官方推出的数据迁移工具&#xff0c;能够满足众多数据迁移场景的需求&#xff0c;现已成为众多用户进行数据迁移同步的重要工具。OMS不仅支持多种数据源&#xff0c;还具备全量迁移、增量同步、数据校验等功能&#xff0c;并能够对分表进行聚合操作&…

文件操作

前言&#xff1a; 文件内容属性 要向访问文件就要打开文件——>用进程来打开——>要把文件先加载到内存中——> 一个进程可以打开多个文件&#xff0c;OS中也有可能多个进程打开了多个文件 文件以多&#xff0c;就需要进行管理&#xff0c;——先描述再组织 没有被打开…

基于Spring Boot框架实现大学生选课管理系统

文章目录 源代码下载地址项目介绍项目功能界面预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目功能 教务处管理 开课、开班审批&#xff0c;排课处理&#xff0c;班级操作&#xff0c;选课时间段管理** 使用了sql解决了开课开班的时间段的冲突…

基于PHP后台微信图书馆借书还书小程序系统设计与实现

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

IDM下载器激活

文章目录 1、Internet Download Manager简介2、Internet Download Managery应用3、Internet Download Managery下载 1、Internet Download Manager简介 Internet Download Manager (IDM) 是一款功能强大的下载管理软件&#xff0c;旨在帮助用户更高效地管理和加速其下载任务。它…