文档章节

线程(并发)

笨蛋图图
 笨蛋图图
发布于 2016/08/05 16:29
字数 2237
阅读 6
收藏 0
点赞 0
评论 0
  1. 线程的创建方式
    class TaskWithResult implements Callable<String>{
        private int id;
    
        public TaskWithResult(int id) {
            this.id = id;
        }
        @Override
        public String call() throws Exception {
            return "result of taskResult is " +id;
        }
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newCachedThreadPool();
            List<Future<String>> list = new ArrayList<>();
            for (int i = 0; i < 5; i++) {
                Future<String> future = executorService.submit(new TaskWithResult(i));
                list.add(future);
            }
            try {
                for (Future<String> future : list) {
                    if(future.isDone()){
                        System.out.println(future.get());
                    }//也可以直接调用get方法,这个时候get会被阻塞,直到task完成之后才被执行 
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    public class TestRunable implements Runnable{
       protected int countDown = 10;
       private static int taskCount = 0;//当前运行的线程计数
       private final int id = taskCount++;//当前线程id标记
       public String status() {
            return "#" + id + "(" + (countDown > 0 ? countDown : "lifeOff") + ")." + taskCount;
       }
       @Override
       public void run() {
          while (countDown >= 0) {
             System.out.println(status());
             Thread.yield();
             countDown--;
          }
       }
       public static void main(String[] args){
           for(int i=0;i<5;i++) {
               Thread t = new Thread(new LifeOff());
               t.start();
           }
       }
    }
    public class TestThread extends Thread{
       protected int countDown = 10;
       private static int taskCount = 0;//当前运行的线程计数
       private final int id = taskCount++;//当前线程id标记
       public String status() {
            return "#" + id + "(" + (countDown > 0 ? countDown : "lifeOff") + ")." + taskCount;
       }
       public void run(){
          while(countDown >= 0){
             System.out.println(status());
             Thread.yield();
             countDown--;
          }
       }
       public static void main(String[] args){
           for(int i=0;i<5;i++){
               Thread a = new TestThread();
               a.start();
           }
       }
    }

     

  2. java线程管理(线程包装器Executors)
    class LifeOff implements Runnable {
        protected int countDown = 10;
        private static int taskCount = 0;
        private final int id = taskCount++;
    
        public LifeOff() {}
    
        public LifeOff(int countDown) {
            this.countDown = countDown;
        }
    
        public String status() {
            return "#" + id + "(" + (countDown > 0 ? countDown : "lifeOff") + ")." + taskCount;
        }
    
        @Override
        public void run() {
            while (countDown >= 0) {
                System.out.println(status());
                Thread.yield();
                countDown--;
            }
        }
    }
    public class JunitTest{
       public void static main(String[] args){
           //创建一个最小线程未0,最大为2的31次方-1,存活时间为60s(空闲线程的存活时间)的线程池
           //会创建和所需数量相同的线程(一个任务对应一个线程),在回收线程时(当线程超过最大容量,且闲置时间超过设置的时间时)停止创建线程
           //是相对合理的线程管理对象
           ExecutorService service = Executors.newCachedThreadPool();
           //当newCachedThreadPool可能会发生问题时,应该考虑另一种方式(指定创建的线程数量)
           ExecutorService service = Executors.newFixThreadPool(3);
           //当需要在某一个线程中长期运行某个任务时,你需要使用SingleThreadExecutor,这个是线程数量为1的FixedTheadPool
           //任何时间任何线程都只有一个任务在运行
           ExecutorService service = Executors.newSingleThreadExecutor();
           for(int i=0;i<5;i++){
               service.execute(new LifeOff());
           }
           service.shutdown();
       }
    }

     

  3. 优先级(听起来好像很高大上,但是我能说没看懂么,测试貌似没什么卵用)
    class SimplePriorities implements Runnable {
        private int countDown = 5;
        private int priority;
        private volatile double d;
    
        public SimplePriorities(int priority) {
            this.priority = priority;
        }
    
        @Override
        public String toString() {
            return Thread.currentThread() + ":" + countDown;
        }
    
        @Override
        public void run() {
            Thread.currentThread().setPriority(priority);
            //通过大量浮点运算,来让线程优先级调度介入,从而主动控制线程(貌似没什么效果,应该还是和OS对CPU调度有关)
            while (true) {
                for (int i = 0; i < 100000; i++) {
                    d += (Math.PI + Math.E) / (double) i;
                    if (i % 1000 == 0) {
                        Thread.yield();
                    }
                }
                System.out.println(this);
                if (--countDown == 0) {
                    return;
                }
            }
        }
    
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (int i = 0; i < 5; i++) {
                executorService.execute(new SimplePriorities(Thread.MIN_PRIORITY));
                executorService.execute(new SimplePriorities(Thread.MAX_PRIORITY));
            }
            executorService.shutdown();
        }
    }

     

  4. 后台线程:通过setDaemon(true)可以设置线程未后台运行,且必须在start()调用前设置;且当所有非后台线程结束后(程序终止),后台线程自动结束
    /**
     * 后台线程
     * 当所有非后台线程结束后,则后台线程自动结束
     * 可以通过修改sleep的时间可以明显看到效果
     */
    class SimpleDaemon implements Runnable{
        @Override
        public void run() {
            try {
                //这里写一个死循环,无限执行当前线程的打印
                while (true) {
                    System.out.println(Thread.currentThread()+"..."+this);
                    TimeUnit.MILLISECONDS.sleep(100);//等同Thread.currentThread().sleep(100)
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            for (int i=0;i<10;i++) {
                Thread thread = new Thread(new SimpleDaemon());
                //设置要执行的线程未后台线程:必须在执行前设置
                thread.setDaemon(true);
                thread.start();
            }
            System.out.println("SimpleDaemon start");
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    //通过实现ThreadFactory来设置线程的一些属性,比如优先级、名称、是否为后台线程(priority,name,daemon等)
    class DaemonThreadFactory implements ThreadFactory{
        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        }
    }
    
    class DaemonFromFactory implements Runnable {
        @Override
        public void run() {
            try {
                //这里写一个死循环,无限执行当前线程的打印
                while (true) {
                    TimeUnit.MILLISECONDS.sleep(100);//等同Thread.currentThread().sleep(100)
                    System.out.println(Thread.currentThread()+"..."+this);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws Exception {
            //通过Executors.newCachedThreadPool(ThreadFactory f)来设置线程的属性
            ExecutorService executorService = Executors.newCachedThreadPool(new DaemonThreadFactory());
            for (int i=0;i<10;i++) {
                executorService.execute(new DaemonFromFactory());
            }
            System.out.println("SimpleDaemon start");
            TimeUnit.MILLISECONDS.sleep(200);
            executorService.shutdown();
        }
    }

     

  5. 线程协作(wait --- notifyAll)
    /**
     * synchronized wait -- notifyAll方式
     * car的抛光和打蜡的并发操作
     */
    class Car {
        /*打蜡是否OK的标记*/
        private boolean waxOn = false;
        /*已经打好蜡OK了,等待抛光*/
        public synchronized void waxed() {
            waxOn = true;
            notifyAll();
        }
        /*已经抛光OK了,等待打蜡*/
        public synchronized void buffed() {
            waxOn = false;
            notifyAll();
        }
        /*如果未打蜡,则等待打蜡*/
        public synchronized void waitForWax()throws InterruptedException {
            while (waxOn == false) {
                wait();
            }
        }
        /*如果打蜡OK了,则等待抛光*/
        public synchronized void waitForBuffed() throws InterruptedException {
            while (waxOn == true) {
                wait();
            }
        }
    }
     
    /**
     * 打蜡
     */
    class WaxOn implements Runnable {
     
        private Car car;
     
        public WaxOn(Car car) {
            this.car = car;
        }
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    /*先判断当前车是否打蜡OK,如果OK,则修改打蜡标记,然后等待抛光*/
    //                car.waitForWax();
                    car.waxed();
                    System.out.println("打蜡完成。。。");
                    car.waitForBuffed();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     
    /**
     * 抛光
     */
    class Buffed implements Runnable {
     
        private Car car;
     
        public Buffed(Car car) {
            this.car = car;
     
        }
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    /*先判断是否打蜡OK了,如果打蜡OK,则进行抛光,然后等待打蜡*/
                    car.waitForWax();
                    System.out.println("正在抛光中。。。");
                    car.buffed();
    //                car.waitForWax();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     
    class CarTest {
     
        public static void main(String[] args) throws InterruptedException{
            Car car = new Car();
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (int i=0;i<3;i++) {
                executorService.execute(new WaxOn(car));
                executorService.execute(new Buffed(car));
                TimeUnit.MILLISECONDS.sleep(1);
            }
            executorService.shutdownNow();
        }
     
    }
    /**
     * lock方式
     * car的抛光和打蜡的并发操作
     */
    class Car {
        /*打蜡是否OK的标记*/
        private boolean waxOn = false;
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        /*已经打好蜡OK了,等待抛光*/
        public void waxed() {
            lock.lock();
            try {
                waxOn = true;
                condition.signalAll();
            } finally {
                lock.unlock();/*任何情况下都要保证释放锁*/
            }
        }
        /*已经抛光OK了,等待打蜡*/
        public void buffed() {
            lock.lock();
            try {
                waxOn = false;
                condition.signalAll();
            } finally {
                lock.unlock();
            }
        }
        /*如果未打蜡,则等待打蜡*/
        public void waitForWax()throws InterruptedException {
            lock.lock();
            try {
                while (waxOn == false) {
                    condition.await();
                }
            } finally {
                lock.unlock();
            }
        }
        /*如果打蜡OK了,则等待抛光*/
        public void waitForBuffed() throws InterruptedException {
            lock.lock();
            try {
                while (waxOn == true) {
                    condition.await();
                }
            } finally {
                lock.unlock();
            }
        }
    }
     
    /**
     * 打蜡
     */
    class WaxOn implements Runnable {
     
        private Car car;
     
        public WaxOn(Car car) {
            this.car = car;
        }
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    /*先判断当前车是否打蜡OK,如果OK,则修改打蜡标记,然后等待抛光*/
    //                car.waitForWax();
                    car.waxed();
                    System.out.println("打蜡完成。。。");
                    car.waitForBuffed();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     
    /**
     * 抛光
     */
    class Buffed implements Runnable {
     
        private Car car;
     
        public Buffed(Car car) {
            this.car = car;
     
        }
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    /*先判断是否打蜡OK了,如果打蜡OK,则进行抛光,然后等待打蜡*/
                    car.waitForWax();
                    System.out.println("正在抛光中。。。");
                    car.buffed();
    //                car.waitForWax();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     
    class CarTest {
     
        public static void main(String[] args) throws InterruptedException{
            Car car = new Car();
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (int i=0;i<3;i++) {
                executorService.execute(new WaxOn(car));
                executorService.execute(new Buffed(car));
                TimeUnit.MILLISECONDS.sleep(1);
            }
            executorService.shutdownNow();
        }
     
    }
    /**
     * linkedBlockingQueue(阻塞队列)方式
     * 生产吐司、给吐司添加黄油、给吐司添加果酱
     * 吐司
     */
    class Toast {
    
        /*状态:dry空白吐司,buttered添加好黄油的,jamed添加好果酱的*/
        public enum Status {
            DRY("有吐司"), BUTTERED("有黄油"), JAMED("有果酱");
            private String name;
    
            private Status(String name) {
                this.name = name;
            }
    
            public String getName() {
                return name;
            }
        }
    
        private Status status = Status.DRY;
        private int id;
    
        public Toast(int id) {
            this.id = id;
        }
    
        /*添加黄油*/
        public void butted() {
            status = Status.BUTTERED;
        }
    
        /*添加果酱*/
        public void jamed() {
            status = Status.JAMED;
        }
    
        public Status getStatus() {
            return status;
        }
    
        public int getId() {
            return this.id;
        }
    
        @Override
        public String toString() {
            return "Toast " + id + ":" + status.getName();
        }
    }
    
    class ToastQueue extends LinkedBlockingQueue<Toast> {
        /*设置该队列的容量*/
        public ToastQueue(int i) {
            super(i);
        }
    }
    
    /*生产吐司*/
    class Toaster implements Runnable {
    
        private ToastQueue toastQueue;
        private int count = 0;
    
        public Toaster(ToastQueue toastQueue) {
            this.toastQueue = toastQueue;
        }
    
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    Toast toast = new Toast(count++);
                    System.out.println(toast);
                    /*添加到已经生产好toast的队列*/
                    toastQueue.put(toast);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    /*添加黄油的线程*/
    class Buffer implements Runnable {
    
        private ToastQueue bufferQueue;
        private ToastQueue toastQueue;
    
        public Buffer(ToastQueue toastQueue, ToastQueue bufferQueue) {
            this.bufferQueue = bufferQueue;
            this.toastQueue = toastQueue;
        }
    
        private int count = 0;
    
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    /*取出toast,添加黄油,并存放在已经添加完黄油队列*/
                    Toast toast = toastQueue.take();
                    toast.butted();
                    System.out.println(toast);
                    bufferQueue.put(toast);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    class Jamer implements Runnable {
    
        private ToastQueue bufferQueue;
        private ToastQueue jamerQueue;
    
        public Jamer(ToastQueue bufferQueue, ToastQueue jamerQueue) {
            this.bufferQueue = bufferQueue;
            this.jamerQueue = jamerQueue;
        }
    
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    Toast toast = bufferQueue.take();
                    toast.jamed();
                    System.out.println(toast);
                    jamerQueue.put(toast);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("jam finished");
        }
    }
    
    class Finisher implements Runnable {
    
        private ToastQueue jamerQueue;
        private int        count;
    
        public Finisher(ToastQueue jamerQueue) {
            this.jamerQueue = jamerQueue;
        }
    
        @Override
        public void run() {
            try {
                while (!Thread.interrupted()) {
                    Toast toast = jamerQueue.take();
                    if (toast.getId() != count++ || toast.getStatus() != Toast.Status.JAMED) {
                        System.err.println("不是同一块toast,或者没有添加果酱 " + toast);
                        System.exit(1);
                    } else {
                        System.out.println(toast);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    class ToastTest {
    
        public static void main(String[] args) throws Exception {
            ToastQueue toastQueue = new ToastQueue(1);
            ToastQueue bufferQueue = new ToastQueue(1);
            ToastQueue jamerQueue = new ToastQueue(1);
            ExecutorService executorService = Executors.newCachedThreadPool();
            executorService.execute(new Toaster(toastQueue));
            for (int i = 0; i < 5; i++) {
                executorService.execute(new Buffer(toastQueue, bufferQueue));
                executorService.execute(new Jamer(bufferQueue, jamerQueue));
                executorService.execute(new Finisher(jamerQueue));
            }
            TimeUnit.MILLISECONDS.sleep(50);
            executorService.shutdownNow();
        }
    
    }
    /*
     * 使用管道必须保证输入输出的对象创建完成(如main方法中new2个对象),否则在不同平台会发生不一致问题
     * 理论不建议使用管道来操作线程协作,建议使用BlockQueue更方便,也更安全
     *管道写入端
     * */
    class Sender implements Runnable {
    
        private PipedWriter pipedWriter;
    
        public Sender(PipedWriter pipedWriter) {
            this.pipedWriter = pipedWriter;
        }
        public PipedWriter getPipedWriter() {
            return pipedWriter;
        }
        @Override
        public void run() {
            try {
                while (true) {
                    for (char i = 'A'; i <= 'z'; i++) {
                        pipedWriter.write(i);
                    }
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException ee) {
                ee.printStackTrace();
            }
        }
    }
    /*管道接收端*/
    class Receiver implements Runnable {
    
        private PipedReader reader;
    
        private Sender sender;
    
        public Receiver(Sender sender) throws Exception{
            reader = new PipedReader(sender.getPipedWriter());
        }
        @Override
        public void run() {
            try {
                while (true) {
                    /*使用reader.read()会在线程池调用shutdownNow()时直接截断,无论reader是否有读完*/
                    System.out.println("Read "+reader.read() + ",");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    class PipedMain {
    
        public static void main(String[] args) throws Exception{
            PipedWriter pipedWriter = new PipedWriter();
            Sender sender = new Sender(pipedWriter);
            Receiver receiver = new Receiver(sender);
            ExecutorService service = Executors.newCachedThreadPool();
            service.execute(sender);
            service.execute(receiver);
            TimeUnit.MILLISECONDS.sleep(100);
            service.shutdownNow();
        }
    
    }

     

  6.  

© 著作权归作者所有

共有 人打赏支持
笨蛋图图
粉丝 4
博文 19
码字总数 13586
作品 0
杭州
程序员
并发一:JAVA并发模型

一、并发 并发程序是指在运行中有两个及以上的任务同时在处理,与之相关的概念并行,是指在运行中有两个及以上的任务同时执行,差别是在于处理和执行。在单核CUP中两个及以上任务的处理方式是...

wangjie2016 ⋅ 2017/05/18 ⋅ 0

读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏 ⋅ 2015/11/11 ⋅ 1

读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏 ⋅ 2015/11/11 ⋅ 8

Android异步并发类库--Android-lite-go

LiteGo:「迷你」的Android异步并发类库 LiteGo是一款基于Java语言的「异步并发类库」,它的核心是一枚「迷你」并发器,它可以自由地设置同一时段的最大「并发」数量,等待「排队」线程数量,...

匿名 ⋅ 2016/03/25 ⋅ 0

iOS NSThread、NSOperation与GCD

一、NSThread线程 优点: NSThread 比其他两个轻量级、使用方便、简洁。 缺点: ①需要自己管理线程的生命周期。 ②线程同步,线程同步对数据的加锁会有一定的系统开销 NSThread线程的使用:...

IamOkay ⋅ 01/15 ⋅ 0

iOS多线程之GCD

1.简介 什么是GCD 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多...

JlongTian ⋅ 2016/01/08 ⋅ 0

tomcat的性能与最大并发(1000)

当一个进程有 500 个线程在跑的话,那性能已经是很低很低了。Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大。 当某个应用拥有 250 个以上并发的...

JasonO ⋅ 2016/03/02 ⋅ 0

并发编程(三):同步容器和并发容器

前言 Java 中有些集合和非线程安全,而有些集合是线程安全,后者又被称为是Java中的同步容器,因为它能满足操作的原子性,保持数据同步。有些容器时Java自带的,而有些是通过Collections提供...

mengdonghui123456 ⋅ 2017/08/15 ⋅ 0

Concurrent and Parallel

并发: 当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代...

Jack崔 ⋅ 2017/07/17 ⋅ 0

MySQL 5.6.17/Percona5.6.16/MariaDB 10.0.11/OneSQL 5.6.16压测瓶颈分析

之前我进行了MySQL 5.6.17/Percona5.6.16/MariaDB 10.0.11/OneSQL 5.6.16对比基准TPCC压测,从测试结果可以看到在高并发(并发1920线程)模式下,MariaDB的相对优势,也看到了在一般并发场景...

鉴客 ⋅ 2014/06/09 ⋅ 7

没有更多内容

加载失败,请刷新页面

加载更多

下一页

vim编辑模式、命令模式

编辑模式 vim要从一般模式进入编辑模式只要按字母 i 、I、a、A、o、O键就可以了 要从编辑模式回到一般模式按键盘上的Esc键即可。 按键 作用 i 在当前字符前插入 I 在光标所在行的行首插入 o ...

黄昏残影 ⋅ 25分钟前 ⋅ 0

OSChina 周五乱弹 —— 如果有一天不当程序员了

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @guanglun :分享off的单曲《我唱情歌给你听》 《我唱情歌给你听》- off 手机党少年们想听歌,请使劲儿戳(这里) @小小编辑 :#如果不做程序...

小小编辑 ⋅ 32分钟前 ⋅ 4

从 Confluence 5.3 及其早期版本中恢复空间

如果你需要从 Confluence 5.3 及其早期版本中的导出文件恢复到晚于 Confluence 5.3 的 Confluence 中的话。你可以使用临时的 Confluence 空间安装,然后将这个 Confluence 安装实例升级到你现...

honeymose ⋅ 今天 ⋅ 0

Java8新增的DateTimeFormatter与SimpleDateFormat的区别

两者最大的区别是,Java8的DateTimeFormatter也是线程安全的,而SimpleDateFormat并不是线程安全。 在并发环境下使用SimpleDateFormat 为了能够在多线程环境下使用SimpleDateFormat,有这三种...

人觉非常君 ⋅ 今天 ⋅ 0

多线程如何控制执行顺序

线程的生命周期说明: 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、...

MarinJ_Shao ⋅ 今天 ⋅ 0

用ZBLOG2.3博客写读书笔记网站能创造今日头条的辉煌吗?

最近两年,著名的自媒体网站今日头条可以说是火得一塌糊涂,虽然从目前来看也遇到了一点瓶颈,毕竟发展到了一定的规模,继续增长就更加难了,但如今的今日头条规模和流量已经非常大了。 我们...

原创小博客 ⋅ 今天 ⋅ 0

MyBatis四大核心概念

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper)。 MyBatis 作为互联网数据库映射工具界的“上古神器”,训有四大“神兽”,谓之:Sql...

waylau ⋅ 今天 ⋅ 0

以太坊java开发包web3j简介

web3j(org.web3j)是Java版本的以太坊JSON RPC接口协议封装实现,如果需要将你的Java应用或安卓应用接入以太坊,或者希望用java开发一个钱包应用,那么用web3j就对了。 web3j的功能相当完整...

汇智网教程 ⋅ 今天 ⋅ 0

2个线程交替打印100以内的数字

重点提示: 线程的本质上只是一个壳子,真正的逻辑其实在“竞态条件”中。 举个例子,比如本题中的打印,那么在竞态条件中,我只需要一个方法即可; 假如我的需求是2个线程,一个+1,一个-1,...

Germmy ⋅ 今天 ⋅ 0

Django第一期

安装Django 去https://www.djangoproject.com/download/ 下载最新版的Django,然后解压放到Anaconda\Lib\site-packages目录下,然后cmd进入此目录,输入安装命令: python setup.py install ...

大不了敲一辈子代码 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部