精华内容
下载资源
问答
  • 1.在登录处打断点,同时登陆两个账号,此时两个登陆都会被... ...还是会被拦截。 2.改变断点状态为thread。(阻塞所有变为阻塞线程级别) 此时登录一个账号后放开断点。在登陆其他账号,其他账号登录不会被拦截。 ...

    1.在登录处打断点,同时登陆两个账号,此时两个登陆都会被拦,

    即使在第一个账户点击登陆后,取消断点(取消断点不是放过断点),此时点击第二个账号登陆。还是会被拦截。

    2.改变断点状态为thread。(阻塞所有变为阻塞线程级别)

    此时登录一个账号后放开断点。在登陆其他账号,其他账号登录不会被拦截。

    展开全文
  • 单例在多线程下是安全的? 多例在多线程下是安全的? Tomcat每个请求都会在一个线程中执行,那所有的java代码是否都要考虑线程安全问题? 3.1. Spring单例模式下要...一个对象是单例还是多例,与它是否是线程安全的
    1. 单例在多线程下是安全的?
    2. 多例在多线程下是安全的?
    3. Tomcat每个请求都会在一个线程中执行,那所有的java代码是否都要考虑线程安全问题?
      3.1. Spring单例模式下要不要考虑?看看平时的代码是怎么写的?
      3.2. Struts2多例模式下要不要考虑?看看平时的代码是怎么写的?
    4. 单例在单线程下是安全的?
    5. 多例在单线程下是安全的?

    结论:
    一个对象是单例还是多例,与它是否是线程安全的,没有什么关系,没有关系!!!
    一个对象不管是多例还是单例,当多个线程同时访问一个对象(一个对象)的时候,都要考虑安全问题。

    最终一个对象是单例还是多例,就看他new了几个对象,而且只能决定对象的个数,不能绝对对象是否线程安全。
    一个对象是不是线程安全的,只看它的写法,与创建几个对象(单例和多例)没有关系,它是线程安全的就是线程安全的,你创建一个和创建100个,它就是线程安全的。
    展开全文
  • 前言netty的学习有以下几个难点:netty基于nio进行了较为复杂...其实io 模型的多线程扩展方面,不论bio 还是nio 宏观上都类似,这一点可以与 《how tomcat works》笔记 对比着看,tomcat 在演化的过程中,也由单纯的...

    前言

    netty的学习有以下几个难点:netty基于nio进行了较为复杂的封装,而很多童鞋对nio都不是很了解。建议先查看 java NIO

    netty中应用了Reactor模式,而Reactor模式本身有多种线程模型可以实现。其实io 模型的多线程扩展方面,不论bio 还是nio 宏观上都类似,这一点可以与 《how tomcat works》笔记 对比着看,tomcat 在演化的过程中,也由单纯的操作socket 演进为提供 HttpConnector、HttpProcessor抽象。其背后都符合多线程扩展的基本思想:找到串行任务中的并行部分(逻辑上不相关/弱相关),将一个线程的事情拆分到多个线程中

    为减少篇幅,本文涉及的所有代码忽略了次要部分及异常处理,所有代码可以在[email protected]:lqk654321/nio-demo.git下载。

    本文从最简单的代码开始,逐步拆解,演示下如何在nio编程中应用各种线程模型。

    单线程模型

    public class NIOServer {

    public static void main(String[] args) throws IOException {

    Selector selector = Selector.open();

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

    serverSocketChannel.configureBlocking(false);

    serverSocketChannel.socket().bind(new InetSocketAddress(8080));

    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    while (true) {

    selector.select(1000);

    Set selectedKeys = selector.selectedKeys();

    Iterator it = selectedKeys.iterator();

    SelectionKey key = null;

    while (it.hasNext()) {

    key = it.next();

    it.remove();

    handleKey(key);

    }

    }

    }

    public static void handleKey(SelectionKey key) throws IOException {

    if (key.isAcceptable()) {

    // Accept the new connection

    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

    SocketChannel sc = ssc.accept();

    sc.configureBlocking(false);

    // Add the new connection to the selector

    sc.register(key.selector(), SelectionKey.OP_READ | SelectionKey.OP_WRITE);

    System.out.println("accept...");

    } else if (key.isReadable()) {

    SocketChannel sc = (SocketChannel) key.channel();

    ByteBuffer readBuffer = ByteBuffer.allocate(1024);

    // handle buffer

    int count = sc.read(readBuffer);

    if (count > 0) {

    String receiveText = new String(readBuffer.array(), 0, count);

    System.out.println("服务器端接受客户端数据--:" + receiveText);

    }

    }

    }

    }

    代码中,while(true){监听并处理事件}循环有个学名,叫eventloop。

    while(ture){

    // 阻塞

    selectKeys = select();

    // 非阻塞

    handleKey(selectKeys);

    }

    在该示例中,所有工作放在一个线程中处理,很明显可靠性较低且性能不高。从事件属性上讲,包括:accept事件、read/write事件。

    从任务属性上讲,包括io任务(r/w data),read/write数据的处理(对data的业务处理)等事件任务(处理事件)accept新连接进来将新连接的socket注册到selector

    read读缓冲区有数据数据解码、进行业务处理

    write写缓冲区有空闲数据编码,写入socket send buffer

    对于server端,连接建立得到socket后,要为新建立的socket的注册selector(在我以前的理解中,忽视了这一点)。

    f4854aef031a9015712ecaa5548995e7.png

    多线程模型——io线程和业务线程分开

    最容易想到的办法,当数据readable时,启动线程池,开启一个新的任务专门处理该数据,高大上点就是:io线程和业务线程分开,因此上节的handlerKey方法简化成了。

    public static void handleKey(SelectionKey key) throws IOException {

    if (key.isAcceptable()) {

    // Accept the new connection

    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

    SocketChannel sc = ssc.accept();

    sc.configureBlocking(false);

    // Add the new connection to the selector

    sc.register(key.selector(), SelectionKey.OP_READ | SelectionKey.OP_WRITE);

    System.out.println("accept...");

    } else if (key.isReadable()) {

    executor.execute(new Reader(key));

    }

    }

    对应的,红色部分交给线程池处理事件任务(处理事件)accept新连接进来将新连接的socket注册到selector

    read读缓冲区有数据数据解码、进行业务处理

    write写缓冲区有空闲数据编码,写入socket send buffer

    主从线程模型——io线程按事件类型分开

    到目前为止,代码还没有完全并行化,因为acceptable事件和readable/writable事件的处理,也没什么关系。于是我们可以搞两个selector(笔者以前默认的意识里,一直以为selector只能有一个。当笔者看到可以两个selector监听不同事件的时候,一下子对netty豁然开朗了),一个负责监听acceptable事件,一个监听readable/writable事件的处理,分散在不同的线程中处理。

    public class NIOServer {

    private static ExecutorService boosExecutor = Executors.newFixedThreadPool(1);

    private static ExecutorService workerExecutor = Executors.newFixedThreadPool(10);

    private static Queue workerQueue = new ConcurrentLinkedQueue();

    public static void main(String[] args) throws IOException {

    /**

    * boss只处理连接事件,worker只处理读写事件。

    * 将两者分开的关键就是使用两个selector

    */

    Selector bossSelector = Selector.open();

    Selector workerSelector = Selector.open();

    Boss boss = new Boss(bossSelector,workerQueue);

    boss.bind();

    boosExecutor.execute(boss);

    workerExecutor.execute(new Worker(workerSelector,workerQueue));

    }

    }

    boss线程实现

    public class Boss implements Runnable {

    public void bind() throws IOException {

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

    serverSocketChannel.configureBlocking(false);

    serverSocketChannel.socket().bind(new InetSocketAddress(8080));

    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    }

    public void run() {

    while (true) {

    selector.select();

    Set selectedKeys = selector.selectedKeys();

    Iterator it = selectedKeys.iterator();

    SelectionKey key = null;

    while (it.hasNext()) {

    key = it.next();

    it.remove();

    handleKey(key);

    }

    }

    }

    private void handleKey(SelectionKey key) throws IOException {

    if (key.isAcceptable()) {

    // Accept the new connection

    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

    SocketChannel sc = ssc.accept();

    System.out.println("boss connect...");

    // 向woker队列中发送建立连接的SocketChannel

    workerQueue.add(sc);

    System.out.println("boss queue size " + workerQueue.size());

    }

    }

    }

    worker线程实现

    public class Worker implements Runnable {

    public void run() {

    while (true) {

    process(workerQueue);

    process(selector);

    Thread.sleep(1000);

    }

    }

    public void process(Queue queue) throws IOException{

    // 如果队列为空,会返回null,不会阻塞

    SocketChannel sc = workerQueue.poll();

    if(null != sc){

    System.out.println("worker accept ...");

    sc.configureBlocking(false);

    sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);

    }

    }

    public void process(Selector selector) throws IOException{

    //此处必须设置超时,因为最开始worker的selector没有绑定SocketChannel,所以“selector.select()会阻塞,并且再也无法恢复”

    selector.select(1000);

    // 处理读写事件

    Set selectedKeys = selector.selectedKeys();

    Iterator it = selectedKeys.iterator();

    SelectionKey key = null;

    while (it.hasNext()) {

    key = it.next();

    it.remove();

    handleKey(key);

    }

    }

    }

    对应的,蓝色部分由boss线程(group)负责,红色部分由worker线程(group)负责。事件任务(处理事件)accept新连接进来将新连接的socket注册到selector

    read读缓冲区有数据数据解码、进行业务处理

    write写缓冲区有空闲数据编码,写入socket send buffer

    io线程与selector 绑定

    io 线程的分化是随着 selector 功能的分化进行的,每个io线程都会聚合一个selector

    XXthread{

    private Selector selector

    public void run(){

    while(true){

    selector.select();

    Set selectedKeys = selector.selectedKeys();

    ...

    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

    ...

    }

    }

    }

    kafka 中 专门负责acceptable事件 线程称为 acceptor thread, 负责readable/writable事件的称为 processor thread。netty 中都称为 eventloop,但在使用时命名有所区分,前者称之为boss,后者称之为worker。netty的处理方式也体现了,“io线程与业务线程分化” 与 “io线程本身的分化” 有一点不同:后者虽然分化了,但不同线程整体的处理逻辑是一致的。就好比一些rpc 框架支持快慢线程池的功能,快慢线程池中不同线程的处理逻辑是一样的,只是为了优先保证重要业务的可靠性才做的区分。

    java 多线程编程中,一般推荐将自己的逻辑封装为Runnable提交给线程池。但在很多框架的实现中,通常会将 thread 和 相关数据封装一下 对外提供系统的操作对象,这类对象通常不聚合thread 对象也没有什么问题。按照“程序=控制+逻辑”的公式,此时的线程只是一个“控制”方式,并不影响 封装对象对外提供的 逻辑接口,我们从 reactor 模式的概念图中也没找到 thread的影子不是。

    ffea2df56f8f9d22dd768996a360c0e5.png

    io线程和业务线程的数据交互

    在netty 中,io线程读取到数据后,可以直接操作线程池对象来执行 业务处理逻辑。kafka 则在io 线程与业务线程之间 提供了一个队列来缓冲数据,Processor thread 将读取的数据放入 RequestChannel(对队列的封装),Handler thread读取 并将处理后的响应通过 RequestChannel 传递给Processor。 Handler thread 属于kafka的 API层。

    2c03145adbaf40bb4a714210b1bea8fb.png

    NIO的使用套路

    11ed56b767b1c2330295129934b2b38e.png

    在具体实践中,各个框架套路不一样hadoop,Thread-Per-Connection,与BIO的思路一样,只是用了NIO的API

    kafka客户端,一个线程 一个selector 裸调java NIO 进行网络通信

    netty和kafka 服务端都采用主从线程模型,但在io线程和业务线程的交互上有差异,如上文所述

    展开全文
  • 批处理多开Tomcat

    2018-04-28 09:44:30
    想测试下tomcat能承载的高并发支持能够达到多少但是随着后续的并发压力测试,考虑到单个Tomcat的最大线程数问题及处理能力,使用到了Nginx负载均衡,我想让并发量能达到一个新的突破,单tomcat测试,我修改了tomcat...

    最近在进行并发裸机测试,想测试下tomcat能承载的高并发支持能够达到多少

    但是随着后续的并发压力测试,考虑到单个Tomcat的最大线程数问题及处理能力,使用到了Nginx负载均衡,我想让并发量能达到一个新的突破,单tomcat测试,我修改了tomcat最大连接数但是还是会出现当并发达到200时出现链接被拒绝的情况

    从而使用到Nginx做tomcat集群处理,让tomcat能够分摊压力,修改了tomcat的配置文件后,我要一次打开5个tomcat,因为我使用的是本地开发环境,windows10的系统,所以我得依次执行tomcat的startup.bat文件让其启动。讲真,如果你一个一个的跑到对应tomcat目录下去打开tomcat真的好累

    所以考虑到这一点使用到了批处理来执行,我要让我的批处理执行能够一次打开所有的tomcat

    然而  当我使用call 指令到对应tomcat目录下进行打开tomcat时,tomcat反馈的信息是要求存在tomcat的环境变量。

    为什么一个tomcat还需要环境变量?感觉有点非人类了,只是一个接口服务罢了。

    然而要让我这么做就这么做吧,不想去看tomcat的批处理及内部。于是我使用到了set命令进行赋值,我为其想要的环境变量依次赋值,这样我的tomcat算是启动成功了。

    附上批处理的代码:


    展开全文
  • Java多线程初步了解

    2015-02-02 20:09:27
    好吧,因为要找实习笔试面试了,所以根据师兄给的书单,了解一下java多线程了,tomcat等知识,今天就先谈谈java多线程 了。回想一下咯,操作系统里面有关进程和线程的关系,一直以为很虚的东西,那是因为之前没写过...
  • Tomcat请求处理流程

    2019-12-28 19:35:51
    首先了解一下并发访问:指路客户端同时访问一台服务器 Tomcat服务器支持路并发访问,个用户可以同时访问...凭一个路径,不能判断是Servlet还是文件 例如: /image/120.jpg, 它看起来是一个文件,但也可能...
  • 2018.8.6面试总结

    2018-08-06 19:35:54
    杭州嘀嗒投资管理有限公司面试记录 数据库多线程修改操作怎么处理 ...Redis是单线程还是多线程的 艾希汇先,环境是真的好,还有咖啡机 Mysql存储引擎 索引失效条件 mysql怎么调优 分布式的问题 前端知识...
  • 腾讯前端二面2018-08-17

    2018-08-18 09:53:44
    目前处于复试阶段,不知道后面还会不会有面试,哎,自求多福~~~好累 事件冒泡 一般浏览器是先捕获还是先... apache的原理,是单线程还是多线程还是多进程还是单进程 c++里面的编译主要做什么?(解析语法?) 操...
  • Netty有三种线程模型:单线程多线程、主从线程。Netty官方推荐使用主从线程组,因为主从线程组比较高效。因为任何的服务器,不管是tomcat还是Jetty,都会有一个启动的类bootstrap。这样的一个Server类我们也会通过...
  • java面试题

    2018-01-01 15:35:15
    72.9. action是实例还是多实例,为什么? 73 72.10. Struts的validate框架是如何验证的? 74 72.11. dispatchAction是用什么技术实现的? 74 72.12. struts2.0的mvc模式?与struts1.0的区别? 74 72.13. struts1.2...
  • 与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
  • java 面试题 总结

    2009-09-16 08:45:34
    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...
  • 采用多线程阻塞模型,也就是说每个请求都会占用一个独立的线程资源,而线程在JVM中是一个相对比较重的资源。当应用是CPU密集型的或者说依赖的远程服务都正常工作时,这种模型能够很好的满足需求&#...
  • java基础题 很全面

    2009-05-09 09:24:24
    44. 多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 12 45. 线程的基本概念、线程的基本状态以及状态之间的关系 12 46. 在linux下 怎么查看tomcat的进程? 12 47. 简述逻辑操作(&,|,^)与条件操作(&&,||...
  • Java面试宝典2010版

    2011-06-27 09:48:27
    50、多线程有几种实现方法?同步有几种实现方法? 51、启动一个线程是用run()还是start()? . 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 53、线程的基本概念、线程...
  • 最新Java面试宝典pdf版

    热门讨论 2011-08-31 11:29:22
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • 一文带你搞懂API网关

    2020-12-28 06:45:32
    比如Tomcat默认就是200个线程,如果网关隔离没有做好的话,当发生网络延迟、FullGC、第三方服务慢等情况造成上游服务延迟时,线程池很容易会被打满,造成新的请求被拒绝,但这个时候...
  • Java面试宝典2012版

    2012-12-03 21:57:42
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本...
  • Java面试宝典-经典

    2015-03-28 21:44:36
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • Java面试宝典2012新版

    2012-06-26 19:20:00
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • java面试宝典2012

    2012-12-16 20:43:41
    50、多线程有几种实现方法?同步有几种实现方法? 36 51、启动一个线程是用run()还是start()? . 37 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 37 53、线程的基本概念...
  • 50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • Java面试笔试资料大全

    热门讨论 2011-07-22 14:33:56
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • JAVA面试宝典2010

    2011-12-20 16:13:24
    50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • 50、多线程有几种实现方法?同步有几种实现方法? 33 51、启动一个线程是用run()还是start()? . 33 52、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 33 53、线程的基本概念...
  • 3.1 线程隔离 43 3.2 进程隔离 45 3.3 集群隔离 45 3.4 机房隔离 46 3.5 读写隔离 47 3.6 动静隔离 48 3.7 爬虫隔离 49 3.8 热点隔离 50 3.9 资源隔离 50 3.10 使用Hystrix实现隔离 51 3.10.1 Hystrix简介 51 3.10.2...
  • 3.3.1 多线程的优缺点 3.3.2 长连接与短连接 3.3.3 二分图应用于最佳匹配问题(游客对房间的满意度之和最大问题) 3.3.4 class与struct的区别? 3.3.5 虚函数和纯虚函数 3.3.6 menset()函数 3.3.7 实现一个...
  • 轻松把玩HttpClient之封装HttpClient工具类(四),单线程调用及多线程批量调用测试 本文主要来分享一下该工具类的测试结果。工具类的整体源码不再单独分享,源码基本上都已经在文章中了。 开始我们的测试。单线程...

空空如也

空空如也

1 2
收藏数 38
精华内容 15
关键字:

tomcat单线程还是多线程