<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[斜杠码农]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/twjjava</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; twjjava]]></copyright><item><title><![CDATA[git如何删除误提交本该忽略的文件夹]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/138319609</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/138319609</guid><author>twjjava</author><pubDate>Mon, 29 Apr 2024 17:20:15 +0800</pubDate><description><![CDATA[我新建完springboot项目后，误提交了.mvn目录、mvnw、mvnw.cmd文件。git commit -am "删除误提交 .mvn mvnw mvnw.cmd"1.在.gitignore文件中添加需要忽略的文件。注意：如果不成功，就在-r后面加个-f再次执行。2.移除误提交的文件。]]></description><category></category></item><item><title><![CDATA[redis相关面试题]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/134689036</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/134689036</guid><author>twjjava</author><pubDate>Wed, 29 Nov 2023 14:34:42 +0800</pubDate><description><![CDATA[volatile-ttl: 回收在过期集合的键，并且优先回收存活时间（TTL）较短的键,使得新添加的数据有空间存放。volatile-lru: 尝试回收最少使用的键（LRU），但仅限于在过期集合的键,使得新添加的数据有空间存放。volatile-random: 回收随机的键使得新添加的数据有空间存放，但仅限于在过期集合的键。allkeys-lru: 尝试回收最少使用的键（LRU），使得新添加的数据有空间存放。allkeys-random: 回收随机的键使得新添加的数据有空间存放。数据快照 (RDB)]]></description><category></category></item><item><title><![CDATA[Kafka相关面试题]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/134688848</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/134688848</guid><author>twjjava</author><pubDate>Wed, 29 Nov 2023 14:20:23 +0800</pubDate><description><![CDATA[因此你可以指定 partition，将相应的消息发往同 1个 partition，并且在消费端，Kafka 保证1 个 partition 只能被1 个 consumer 消费，就可以实现这些消息的顺序消费。对于消息队列来说，出现重复消息的概率还是挺大的，不能完全依赖消息队列，而是应该在业务层进行数据的一致性幂等校验。另外，你也可以指定 key（比如 order id），具有同 1 个 key 的所有消息，会发往同 1 个partition，那这样也实现了消息的顺序消息。2、kafka中ack的三种机制。]]></description><category></category></item><item><title><![CDATA[java面试-zookeeper]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/134536012</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/134536012</guid><author>twjjava</author><pubDate>Tue, 21 Nov 2023 17:02:10 +0800</pubDate><description><![CDATA[在提交阶段，Leader 将提案发送给所有节点，并等待多数节点的确认。在这个阶段，Zookeeper集群中的所有节点都会参与选举，并且需要确保最终选出的Leader是正确的。也就是说，所有写操作会先到 Leader 节点，然后 Leader 节点在通过 2PC（两阶段提交：预提交、ACK、确认提交等流程）来进行数据同步，当写入成功过半就认为信息写入成功。ZAB 协议还包括了崩溃恢复机制，当 Leader 节点崩溃时，系统会选择一个新的 Leader 来取代原先的 Leader 节点。1、什么是zap协议。]]></description><category></category></item><item><title><![CDATA[初识Kubernetes]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/106356842</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/106356842</guid><author>twjjava</author><pubDate>Tue, 21 Nov 2023 16:52:37 +0800</pubDate><description><![CDATA[1、Kubernetes主要由以下几个核心组件组成

etcd保存了整个集群的状态
	apiserver提供资源操作的唯一入口，提供认证，授权，访问控制，api注册和发现等机制
	controller manager负责维护集群的状态，比如故障检测，自动扩展，滚动更新等
	scheduler负责资源调度，按照预定的调度策略将pod调度到相应的机器
	kubelet负责维护容器的生命周期，同时也负责Volume（CVI）和网络（CNI）的管理；
	container runtime负责镜像管理以及pod和容器]]></description><category></category></item><item><title><![CDATA[java并发-Exchanger]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130761100</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130761100</guid><author>twjjava</author><pubDate>Fri, 19 May 2023 10:18:43 +0800</pubDate><description><![CDATA[Exchanger的底层实现基于AQS（AbstractQueuedSynchronizer）同步器，并使用了类似于管道的结构，它维护了两个格子，一个是slot1，另一个是slot2，线程1放入的对象会保存在slot1中，线程2放入的对象会保存在slot2中，当双方都调用exchange()方法时，会互相交换slot中的对象，并返回，让线程1获取到线程2放入的对象，线程2获取到线程1放入的对象，然后两个格子就会重新变成空的，以便下一次交换使用。可以看到，两个线程交换了自己的数据，并接收到了对方交换的数据。]]></description><category></category></item><item><title><![CDATA[java并发-Semaphore]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130761059</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130761059</guid><author>twjjava</author><pubDate>Fri, 19 May 2023 10:17:24 +0800</pubDate><description><![CDATA[它通过一个计数器来表达可用资源的数量，当有新线程需要访问该资源时，会先进行请求，然后进行P（proberen）操作，如果此时计数器的值为0，则线程就会被阻塞并进入等待队列中，等到其他线程释放资源后才重新获得控制权。本文中介绍了Semaphore的简介、底层实现和应用场景，同时演示了Semaphore在生产消费模型中的实现方式，相信读者可以通过本文进一步熟悉Semaphore的使用方法，从而提高对Java并发编程的理解和实践能力。需要注意的是，一旦线程获取到许可证资源，则许可证数量就会减1。]]></description><category></category></item><item><title><![CDATA[java并发-CountDownLatch]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130760993</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130760993</guid><author>twjjava</author><pubDate>Fri, 19 May 2023 10:13:54 +0800</pubDate><description><![CDATA[下面是一个简单的CountDownLatch的例子，使用了2个线程协同工作，主线程等待两个线程都执行完毕后再输出"All threads have finished."1. CountDownLatch是一次性的，计数器的值减为0后，就无法再次使用。3. CountDownLatch是一次等待，线程等待多少次唤醒多少次，而CyclicBarrier是多次等待，线程等待一次，唤醒多次。2. CountDownLatch的计数器是顺序倒减的，而CyclicBarrier的计数器是可循环的。]]></description><category></category></item><item><title><![CDATA[java并发-CyclicBarrier]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130760913</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130760913</guid><author>twjjava</author><pubDate>Fri, 19 May 2023 10:11:33 +0800</pubDate><description><![CDATA[CyclicBarrier的内部状态主要由两个变量组成：一个是“参与者数目”，表示需要等待的线程数，另一个是“屏障状态”，表示屏障是否已经被打破。当所有线程都到达屏障，屏障状态变为true，线程们被唤醒，执行继续。1. 数据分块：当我们需要并行处理一段很大的数据时，可以把它分成多个小块，让每一个线程处理一块，等所有线程都完成后，再把它们组合起来。3. 循环计算：如果需要多次重复计算一个任务，可以使用CyclicBarrier来让所有线程在每次计算完成后等待，直到所有线程都完成一次计算，再开始下一次计算。]]></description><category></category></item><item><title><![CDATA[java并发-Condition]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130760790</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130760790</guid><author>twjjava</author><pubDate>Fri, 19 May 2023 10:08:42 +0800</pubDate><description><![CDATA[当某个线程想要通知Condition中的其他线程时，它将会唤醒等待队列中的一个线程。在increase()方法中，我们先通过lock.lock()获得锁，然后进入while循环，当count的值大于等于10时，调用condition.await()方法将该线程加入等待队列，并释放锁。在decrease()方法中也使用了类似的机制，通过while循环和condition.await()方法等待条件满足，然后更新count的值，并调用condition.signalAll()方法唤醒等待中的线程。]]></description><category></category></item><item><title><![CDATA[java并发-ReentrantReadWriteLock]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130746417</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130746417</guid><author>twjjava</author><pubDate>Thu, 18 May 2023 14:30:30 +0800</pubDate><description><![CDATA[在使用 ReentrantReadWriteLock 时，如果有线程持有写锁，那么其他线程无法获取读锁或写锁。如果有线程请求写锁，也会被阻塞。在使用它时，需要注意调用 lock() 和 unlock() 方法，尽可能多地使用读锁，减少写锁。使用 ReentrantReadWriteLock 非常简单，只需要创建一个 ReentrantReadWriteLock 对象，然后使用 lock() 和 unlock() 方法进行锁操作即可。如果有线程持有读锁，那么其他线程可以继续获取读锁，但无法获取写锁。]]></description><category></category></item><item><title><![CDATA[java并发-ReentrantLock]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130746263</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130746263</guid><author>twjjava</author><pubDate>Thu, 18 May 2023 14:28:34 +0800</pubDate><description><![CDATA[对于公平锁，`tryAcquire` 方法中会先检查队列中是否有等待锁的线程，如果有的话，当前线程就不会去争抢锁，而是会进入到等待队列中，等待锁被释放后再次尝试获取锁。ReentrantLock是ReentrantLock类的实例化对象，其核心方法是lock()和unlock()，在线程访问共享资源时，获取锁之后进行操作，操作完成之后释放锁，以便其他线程也能访问共享资源。对于非公平锁，`tryAcquire` 方法中则直接通过 `CAS` 获取锁，此时不会去检查等待队列中是否有线程在等待锁。]]></description><category></category></item><item><title><![CDATA[java并发-CAS]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130646270</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130646270</guid><author>twjjava</author><pubDate>Fri, 12 May 2023 17:02:58 +0800</pubDate><description><![CDATA[Java中的CAS（Compare and Swap）是一种多线程同步的技术，它是一种无锁算法，也就是说在实现线程同步时不需要使用锁，而是使用了一种乐观锁的思想。Unsafe类是Java中一个不安全的类，因为它提供了一些不安全的操作，如直接访问内存地址、分配内存等。Unsafe类中的compareAndSwapInt()方法可以实现对整型变量的原子性更新，而compareAndSwapObject()方法可以实现对对象引用的原子性更新。Java中的CAS技术是一种无锁算法，可以实现线程安全的操作。]]></description><category></category></item><item><title><![CDATA[java并发-AQS]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130646243</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130646243</guid><author>twjjava</author><pubDate>Fri, 12 May 2023 17:01:07 +0800</pubDate><description><![CDATA[AQS的核心思想是使用一个双向队列来维护等待线程的状态。当一个线程需要获取同步器的状态时，它将会被加入到等待队列的尾部。当同步器的状态被释放时，队列的头部线程将会被唤醒并且获取同步器的状态。AQS的状态是一个整数，表示同步器的状态。在锁的情况下，状态为0表示锁是可用的，状态为1表示锁已经被占用。同步器的状态使用一个整数来表示，可以使用CAS（Compare and Swap）操作来实现原子性的状态修改。- release(int arg)：释放同步器的状态，并唤醒队列中的下一个线程。]]></description><category></category></item><item><title><![CDATA[java-并发-volatile关键字]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130646185</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130646185</guid><author>twjjava</author><pubDate>Fri, 12 May 2023 17:00:17 +0800</pubDate><description><![CDATA[因此，在多线程编程中，我们应该充分了解volatile关键字的特性，遵循Java内存模型的规定，从而编写出高效、正确、可靠的多线程程序。具体来说，当一个线程修改了一个volatile变量时，它会向操作系统发出一个写请求，操作系统会将这个请求发送到所有CPU的缓存中，从而保证了所有线程都可以看到这个变量的最新值。在Java中，volatile关键字是Java内存模型中的一部分。1. 线程之间的可见性：当一个线程修改了一个变量时，它需要将这个变量的值写回到主内存中，以便其他线程可以看到这个变量的最新值。]]></description><category></category></item><item><title><![CDATA[java内存模型-synchronized]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130598116</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130598116</guid><author>twjjava</author><pubDate>Wed, 10 May 2023 12:16:24 +0800</pubDate><description><![CDATA[当一个线程获取锁时，JVM会将对象头中的锁状态改为“偏向锁”，并将当前线程ID记录在对象头中。synchronized关键字的实现机制有对象监视器和基于CAS的机制，为了提高性能，JVM提供了锁消除、锁粗化、轻量级锁和自旋锁等优化机制。其他线程在未获取这个锁之前，无法访问这个同步代码块。当一个线程尝试获取锁时，如果锁已经被其他线程占用，那么这个线程会进入一个循环中，不断尝试获取锁。如果JVM检测到一些同步代码块被频繁地执行，它会将多个同步块合并为一个大的同步块，从而减少锁的获取和释放次数，提高性能。]]></description><category></category></item><item><title><![CDATA[java内存模型]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130598081</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130598081</guid><author>twjjava</author><pubDate>Wed, 10 May 2023 12:10:34 +0800</pubDate><description><![CDATA[即对于所有的操作（包括读和写），Java内存模型要求它们必须按照程序中的顺序执行，且对于每个线程，所有的操作必须是原子的、不可分割的。但是，在多线程程序中，由于线程之间的执行顺序是不确定的，重排序会导致线程之间的执行结果不可预测。总结一下，Java内存模型通过限制重排序、采用顺序一致性、Happens-Before关系和as-if-serial语义等机制，保证了多线程程序的正确性和可预测性。1. 程序顺序规则：在一个线程中，按照程序的顺序，前面的操作Happens-Before于后面的操作；]]></description><category></category></item><item><title><![CDATA[java内存模型-线程通信机制]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/130598029</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/130598029</guid><author>twjjava</author><pubDate>Wed, 10 May 2023 12:05:57 +0800</pubDate><description><![CDATA[需要注意的是，在多线程编程中，线程之间的通信往往是比较复杂的，需要考虑多种因素，如锁的粒度、锁的性质、线程的调度等。同时，需要遵循“尽量少用锁”、“尽量减少线程间通信”等原则，以减少线程之间的竞争和同步开销，提高程序的并发性能。而消息传递则是通过wait()和notify()方法实现线程之间的通信，避免了内存共享所带来的同步和协调问题。也就是说，一个线程对于共享变量的修改，在其他线程读取该变量的值时是能够感知到的。也就是说，对于任何一个共享变量，一个线程的写操作对于其他线程来说是立即可见的。]]></description><category></category></item><item><title><![CDATA[多线程（一）线程生命周期]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/111386158</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/111386158</guid><author>twjjava</author><pubDate>Fri, 18 Dec 2020 17:23:43 +0800</pubDate><description><![CDATA[]]></description><category></category></item><item><title><![CDATA[springboot打包docker 镜像]]></title><link>https://blog.youkuaiyun.com/twjjava/article/details/111036358</link><guid>https://blog.youkuaiyun.com/twjjava/article/details/111036358</guid><author>twjjava</author><pubDate>Fri, 11 Dec 2020 15:31:30 +0800</pubDate><description><![CDATA[准备工作

1、一个打好的jar包

2、一个编好的dockerfile

3、一个装有docker的centos环境

第一步打jar包

在idea的terminal输入mvn clean package

第二步编写dockerfile


FROM java:8
VOLUME /tmp
ADD boot-bucket-0.0.1-SNAPSHOT.jar boot.jar
RUN bash -c "touch /boot.jar"
EXPOSE 8088
ENTRYPOINT ["java","-j]]></description><category></category></item></channel></rss>