实习5.0

wait 为什么一定要跟着synchronized???
wait()的作用是让“当前线程”等待,而“当前线程”是指正在cpu上运行的线程!
websocket协议

Mysql 拥有者变更的解决方案
去终端执行:
sudo chown -R mysql /usr/local/mysql/data

sleep与wait的区别
1、sleep是Thread的静态类方法,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

2、最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
3、sleep不出让系统资源,占着CPU睡觉;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU

Spring Boot默认开启异常应答
-浏览器访问,返回“Whitelabel Error Page”错误页面
-浏览器以外访问返回JSON串:

{"timestamp":1487060396727,
"status":404,
"error":"Not Found",
"message":"No message available",
"path":"/test"} 

Kafka消息队列

Kafka是分布式的发布—订阅消息系统
高吞吐量:可以满足每秒百万级别消息的生产和消费——生产消费。
持久性:有一套完善的消息存储机制,确保数据的高效安全的持久化。
分布式:基于分布式的扩展和容错机制;Kafka的数据都会复制到几台服务器上。当某一台故障失效时,生产者和消费者转而使用其它的机器。

  • 基本概念:
    发送消息者成为Producer,消息接受者成为Consumer
    kafka对消息保存时根据Topic进行归类,每一类的消息称之为一个主题(Topic),消费者可以只关注自己需要的Topic中的消息;
    此外kafka集群有多个kafka实例组成,每个实例称为broker,消息代理,Kafka集群中的一个kafka服务节点称为一个broker,主要存储消息数据;

实习5.0_第1张图片
每一个分区(partition)都是一个 顺序的、不可变的消息队列,并且可以持续的添加。分区中的消息都被分了一个序列号,称之为偏移量(offset), 在每个分区中此偏移量都是唯一的
对于offset的保存和使用,由consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费。 事实上consumer可以使用任意顺序消费消息,它只需要将offset重置为任意值。

即使消息被消费,消息仍然不会被立即删除。日志文件将会根据broker中的配置要求,保留一定的时间之后删除。

在发布-订阅模型中,消息被广播给所有的消费者,接收到消息的消费者都可以处理此消息。
每个partition都有一个server(即kafka实例)为"leader",leader负责所有的读写操作,而follower被动的复制数据。如果leader宕机,其它的一个follower会被推举为新的leader。 一台服务器可能同时是一个分区的leader,另一个分区的follower。

一个partition中的消息只会被group中的一个consumer消费。

实习5.0_第2张图片
Server即为一个Kafka实例

与Spring的集成
未完待续

Zookeeper

实习5.0_第3张图片

Zookeeper设计目的:
1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图

2.可靠性:如果消息被到一台服务器接受,那么它将被所有的服务器接受。

  • 命名服务
    在zookeeper的文件系统里创建一个目录,即有唯一的path。

  • 配置管理
    如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好

  • 集群角色
    一个 ZooKeeper 集群同一时刻只会有一个 Leader,其他都是 Follower 或 Observer(默认不存在观察者)。

Spring eureka 服务治理

实习5.0_第4张图片

Eureka Server: 服务注册中心,负责服务列表的注册、维护和查询等功能;
Service Provider: 服务提供方,同时也是一个Eureka Client,负责将所提供的服务向Eureka Server进行注册、续约和注销等操作。注册时所提供的主要数据包括服务名、机器ip、端口号、域名等,从而能够使服务消费方能够找到;
Service Consumer: 服务消费方,同时也是一个Eureka Client。


什么时候加Synchronized锁

public class Thread1 implements Runnable { 
     public void run() { 
          synchronized(this) { 
               for (int i = 0; i < 5; i++) { 
                    System.out.println(Thread.currentThread().getName() + " synchronized loop " + i); 
               } 
          } 
     } 
     public static void main(String[] args) { 
          Thread1 t1 = new Thread1(); 
          Thread ta = new Thread(t1, "A"); 
          Thread tb = new Thread(t1, "B"); 
          ta.start(); 
          tb.start(); 
     }

当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。

public synchronized void methodA(int a, int b) {
};

public synchronized void methodB(int a){
    methodA(a, 0);
}

//注意:锁住的是Test的实例t
Test t = new Test(); 
t.methodB();   

锁住的是Test的实例t
当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
但是其它线程还是可以访问该被锁住的Object中的非Synchronized实例

什么时候需要加Synchronized锁:
如果有一块代码(或方法)可能被多个线程同时访问,然后里面操作的数据修改操作可能因为不同线程的操作而不一致的时候,使用synchronized锁定这块代码,确保同时只有一个线程访问这个代码块。


Spring cloud Stream

消息发送

public void createOrder(MemberOrder order) {
        CommonMO mo = new CommonMO();
        mo.setMsg("newOrder");
        mo.setData(order);
        ordersSource.memberOrders().send(MessageBuilder.withPayload(mo).build());
    }

会往memberOrders信道里发送流

public interface MemberOrdersSink {
    String ORDERS = "memberOrders";

    @Input
    SubscribableChannel memberOrders();
}
@EnableBinding(MemberOrdersSink.class)
public class MemberOrdersMsgReceiver {

    @StreamListener(MemberOrdersSink.ORDERS)
    public void recordOrder(CommonMO mo) {
    }

再探ReentrantLock 与 Condition

线程级别的定时任务
ScheduledExecutorService与Executors都是java.concurrent.util包下的
建议手动创建线程池

    //线程级别的定时任务
    public void timer() {
//        Calendar c = Calendar.getInstance();
//        c.set(Calendar.HOUR_OF_DAY, 10); // 控制时
//        c.set(Calendar.MINUTE, 0); // 控制分
//        c.set(Calendar.SECOND, 0); // 控制秒
//
//        Date time = c.getTime(); // 得到执行任务的时间,此处为当天的10:00:00

        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
               sendHeartBeat();
            }

        }, 100,7000, TimeUnit.MILLISECONDS);// 这里设定将延时每隔1000毫秒执行一次

    }

如何正确的终止线程

为何不用stop

stop()方法太过于暴力,会强行把执行一半的线程终止。这样会就不会保证线程的资源正确释放,通常是没有给与线程完成资源释放工作的机会.
停掉一个线程将会导致所有已锁定的监听器被解锁,这个之前被监听器锁定的对象被解锁,其他线程就能随意操作这个对象,将导致任何可能的结果。

官方给出的网页说明了不能捕获ThreadDeath异常并修复对象的

yield

使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。cpu会从众多的可执行态里选择,
用了yield方法后,该线程就会把CPU时间让掉,让其他或者自己的线程执行

Java反射定义、获取Class三种方法

反射机制的定义:
在运行状态时(动态的),对于任意一个类,都能够得到这个类的所有属性和方法。
对于任意一个对象,都能够调用它的任意属性和方法。

Class类是反射机制的起源,我们得到Class类对象有3种方法:

第一种:通过类名获得
Class class = ClassName.class;

第二种:通过类名全路径获得:
Class class = Class.forName("类名全路径");

第三种:通过实例对象获得:
Class class = object.getClass();

JDK 动态代理

Java IO 题目
JAVA NIO

Java int 32位
C++ int
int 4 float 4

long 4 double 8

你可能感兴趣的:(实习5.0)