java多线程之notify()的唤醒顺序

在网上看到的额都说notify()的唤醒顺序是随机的,可是自己做的一个实验显示并不是如此:package adad;

public class MyThreadFactory {

// 线程A是否处于等待状态的标志  
 private boolean isThreadAWaiting;  
    // 线程B是否处于等待状态的标志  
    private boolean isThreadBWaiting;  
    // 线程C是否处于等待状态的标志  
    private boolean isThreadCWaiting;  


    public MyThreadFactory() {  
        isThreadAWaiting = true;  
        isThreadBWaiting = true;  
        isThreadCWaiting = true;  
    }  

    /** 
     * 对象锁 
     */  
    private final Object object = new Object();  

    /** 
     * 该线程作为一个唤醒线程 
     */  
    public void startWakenThread() {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    System.out.println("唤醒线程开始执行...");  
                    // 首先释放线程A  
                    quitThreadA();  
                }  
            }  
        });  
        t.start();  
    }  

    /** 
     * 启动线程A 
     */  
    public void startThreadA() {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    System.out.println("线程A开始等待...");  
                    try {  
                        for (; ; ) {  
                            if (!isThreadAWaiting) break;  
                            object.wait();  
                        }  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("线程A结束...");  
                    // 线程A结束后,暂停2秒释放线程B  
                    try {  
                        Thread.sleep(2000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    quitThreadB();  
                }  
            }  
        });  
        t.start();  
    }  

    /** 
     * 启动线程B 
     */  
    public void startThreadB() {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    System.out.println("线程B开始等待...");  
                    try {  
                        for (; ; ) {  
                            if (!isThreadBWaiting) break;  
                            object.wait();  
                        }  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("线程B结束...");  
                    // 线程B结束后,暂停2秒释放线程C  
                    try {  
                        Thread.sleep(2000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    quitThreadC();  
                }  
            }  
        });  
        t.start();  
    }  

    /** 
     * 启动线程C 
     */  
    public void startThreadC() {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    System.out.println("线程C开始等待...");  
                    try {  
                        for (; ; ) {  
                            if (!isThreadCWaiting) break;  
                            object.wait();  
                        }  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("线程C结束...");  

                    try {  
                        Thread.sleep(1000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("所有线程执行完毕!");  
                }  
            }  
        });  
        t.start();  
    }  

    /** 
     * 线程A退出等待 
     */  
    private void quitThreadA() {  
        isThreadAWaiting = false;  
        object.notify();  
    }  

    /** 
     * 线程B退出等待 
     */  
    private void quitThreadB() {  
        isThreadBWaiting = false;  
        object.notify();  
    }  

    /** 
     * 线程C退出等待 
     */  
    private void quitThreadC() {  
        isThreadCWaiting = false;  
        object.notify();  
    }  
   public static void main(String[] args) {  
        MyThreadFactory factory = new MyThreadFactory();  
        factory.startThreadB();//这儿的启动顺序注意
        factory.startThreadA();  

        factory.startThreadC();  

        try {  
            Thread.sleep(3000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        factory.startWakenThread();  
    }  

}

在网上找的这个例子,刚开始启动顺序是ABC,我改成BAC后运行程序多次都唤醒不了,这不正是说明唤醒跟其启动(启动的的时候会有个进入等待池也就是先进先出的顺序吗)

3个回答

看了楼上的回复,发现了一点问题。将他的例子中notify部分改动了一下。

for(int i =1;i<50;i++){
            try {
                Thread.sleep(10);  // 在这里sleep确保notify会顺序执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (a.object) {
                a.object.notify();
            }
        }

最后执行结果:
休眠顺序[1, 4, 7, 6, 5, 2, 3, 10, 9, 13, 8, 12, 14, 11, 16, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 25, 28, 30, 31, 29, 32, 34, 35, 36, 33, 38, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 47, 49]
唤醒顺序[1, 4, 7, 6, 5, 2, 3, 10, 9, 13, 8, 12, 14, 11, 16, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 25, 28, 30, 31, 29, 32, 34, 35, 36, 33, 38, 37, 39, 40, 41, 42, 43, 44, 45, 46, 48, 47, 49]

结果显示唤醒顺序与执行顺序是一样的(注意这里是强调唤醒顺序,而不是重新获得锁的顺序)。
wait后的线程确实是保存在一个FIFO的等待队列中。
为什么楼上的结果唤醒顺序与休眠顺序不一致?
因为他打印的不是唤醒顺序,而是唤醒后线程重新获得锁的顺序。
在循环中直接notify的话,这些等待的线程虽然是按顺序唤醒,但是间隔时间非常短,几乎会同时去竞争锁(这一点和在循环中start线程却不能保证线程执行的顺序是一个道理),因此在竞争下是无法保证获取锁的顺序的。

总结:wait后的线程会进入一个FIFO的队列中,notify是一个有序的出队列的过程。而短时间内多个线程竞争获得锁的顺序则是不确定的,这要靠cpu调度决定。

这个程序,貌似不能用作 线程唤醒无序的例子,每个线程里有两个变量来控制是否能运行,一个是object对象锁,一个是标记变量。

你的唤醒函数的设置标记的顺序是 ABC,但是object的notify不能保证按照ABC唤醒。因此你这个程序实际运行起来应该是有问题的

换句话说,即使你用object.notify(); 唤醒了B。 但是因为标记状态没有被A设置,因此唤醒不了3个线程。

何况你虽然是顺序start三个线程,但不代表这三个线程就一定是按你调用的顺序启动的。 三个线程太少,看不出随机性。

我自己写了一个测试随机唤醒的程序。 结果发现虽然结果不是有规律,但是也不是完全没有规律。 粗看下一个规律是。前面几个休眠的线程会按照顺序唤醒,后面的线程则会倒序唤醒。 具体还需要研究下。

 import java.util.LinkedList;
import java.util.List;

public class ThreadRunSort {

    /** 
     * 对象锁 
     */  
    private final Object object = new Object();  
    private List<Integer> sleep = new LinkedList<>();
    private List<Integer> notify = new LinkedList<>();
    /** 
     * 该线程作为一个唤醒线程 
     */  
    public void startThread(int i) {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    try {
                        System.out.println(Thread.currentThread().getName()+"进入休眠");
                        sleep.add(i);
                        object.wait();
                        System.out.println(Thread.currentThread().getName()+"线程已经唤醒");
                        notify.add(i);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }  
            }  
        });  
        t.setName("Thread"+i);
        t.start();  
    }  

    public static void main(String[] args) {  
        ThreadRunSort a = new ThreadRunSort();
        for(int i =1;i<22;i++){
            a.startThread(i);
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println();
        for(int i =1;i<22;i++){
            synchronized (a.object) {
                a.object.notify();
            }
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("休眠顺序"+a.sleep);
        System.out.println("唤醒顺序"+a.notify);


    }    
}
zxl_LangYa
zxl_LangYa 你这个例子确实比较有实用价值
接近 2 年之前 回复
jumprn
孩子不是海子 谢谢,确实是无序的,是我的实验有误,考虑的太随意
大约 3 年之前 回复

但是如果把代码改成
synchronized (a.object) {
a.object.notifyAll();
}
顺序又变成
休眠顺序[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
唤醒顺序[21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

难道notify是一个有序的出队列的过程,notifyAll是出栈?

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
java多线程中关于使用notify()方法的几个疑问

代码: ``` public class NotifyAndWaitTest2 implements Runnable { public int i = 0; public Object lock; public SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); public NotifyAndWaitTest2(Object o) { this.lock = o; } @Override public void run() { synchronized (lock) { System.out.println(Thread.currentThread().getName() + " enter the SYNCHRONIZED block --- "+ sdf.format(new Date())); try { while (i < 9) { Thread.sleep(500); lock.notify(); lock.wait(); System.out.println(Thread.currentThread().getName() + " say:" + i++ + " --- " + sdf.format(new Date())); } lock.notify(); return; } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { Object lock = new Object(); NotifyAndWaitTest2 test = new NotifyAndWaitTest2(lock); Thread t1 = new Thread(test,"Thread A"); Thread t2 = new Thread(test,"Thread B"); Thread t3 = new Thread(test,"Thread C"); Thread t4 = new Thread(test,"Thread D"); t1.start(); t2.start(); t3.start(); t4.start(); } } ``` 执行结果: ``` Thread A enter the SYNCHRONIZED block --- 10:47:07.242 Thread B enter the SYNCHRONIZED block --- 10:47:07.743 Thread C enter the SYNCHRONIZED block --- 10:47:08.243 Thread D enter the SYNCHRONIZED block --- 10:47:08.743 Thread C say:0 --- 10:47:09.243 Thread D say:1 --- 10:47:09.744 Thread C say:2 --- 10:47:10.244 Thread D say:3 --- 10:47:10.744 Thread C say:4 --- 10:47:11.245 Thread D say:5 --- 10:47:11.745 Thread C say:6 --- 10:47:12.246 Thread D say:7 --- 10:47:12.746 Thread C say:8 --- 10:47:13.247 Thread D say:9 --- 10:47:13.247 Thread B say:10 --- 10:47:13.247 Thread A say:11 --- 10:47:13.247 ``` 这段代码我在 jdk1.7 和 jdk1.8 中都执行过,结果是"相同的" 我主要有两个问题:(以我贴出的这个执行结果为例) 1、在线程A 和线程B 进入了同步代码块之后,并且线程B 调用了 wait() 方法,为什么接下来一定是另外两个线程进入同步代码块?而不是线程A 开始打印 say。是"让新的线程进入同步代码块"的优先级比"调用wait()方法的线程被唤醒"的优先级高吗? 2、为什么调用 notify() 方法只能唤醒最后一个调用了 wait() 方法的线程?就像上面这个执行结果,只有线程C 和线程D 互相唤醒对方,为什么不能唤醒其他的线程,比如线程A 和线程B? 我认为抢对象锁应该是不规律的、随机的,比如这样: ``` Thread A enter the SYNCHRONIZED block Thread B enter the SYNCHRONIZED block Thread A say:0 Thread C enter the SYNCHRONIZED block Thread B say:1 Thread A say:2 Thread D enter the SYNCHRONIZED block Thread B say:3 Thread C say:4 ```

java notify()不是只能唤醒单个线程么,为什么我程序的notify()能唤醒3个

程序是这样的 ``` /* 第一个类*/ public class ThreadB extends Thread{ int total; public void run(){ synchronized(this){ for(int i=0;i<101;i++){ total+=i; } try { sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } notify(); } } public int getTotal(){ return this.total; } } /* 第二个类*/ public class ReaderResult extends Thread{ ThreadB c; public ReaderResult(ThreadB c){ this.c=c; } public void run(){ synchronized (c) { try{ System.out.println(Thread.currentThread()+"等待计算结果。。。。"); c.wait(); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread()+"计算结果为:"+c.getTotal()); } } public static void main(String[] args) { ThreadB calculator = new ThreadB(); ReaderResult reader1=new ReaderResult(calculator); ReaderResult reader2=new ReaderResult(calculator); ReaderResult reader3=new ReaderResult(calculator); reader1.start(); reader2.start(); reader3.start(); calculator.start(); } } ``` 输出结果大多数都 Thread[Thread-1,5,main]等待计算结果。。。。 Thread[Thread-3,5,main]等待计算结果。。。。 Thread[Thread-2,5,main]等待计算结果。。。。 Thread[Thread-1,5,main]计算结果为:5050 Thread[Thread-2,5,main]计算结果为:5050 Thread[Thread-3,5,main]计算结果为:5050 理论上不是只能唤醒一个吗?

java notify 唤醒 wait没有反应

写了一个简单的生产者消费者的小程序,我想要的结果是 producer1 1 consumer1 0 但结果只出现了producer1 1 调试的时候发现,消费者consumer1在进入wait()后没有被唤醒,不知道是为什么,请大神帮忙解答 ``` class Holder{ private int productionNumber=0; private int max=10; private int min=0; public int getNum(){ return productionNumber; } public synchronized void addNum(){ try{ if(productionNumber>=max){ wait(); } else{ productionNumber++; System.out.println(Thread.currentThread().getName()+" "+productionNumber); this.notify(); } } catch(InterruptedException ex){ ex.printStackTrace(); } } public synchronized void subNum(){ try{ if(productionNumber<=min){ wait(); } else{ productionNumber--; System.out.println(Thread.currentThread().getName()+" "+productionNumber); this.notify(); } } catch(InterruptedException ex){ ex.printStackTrace(); } } } class Producer extends Thread{ Holder holder; public Producer(String threadName,Holder holder){ super(threadName); this.holder=holder; } public void run(){ holder.addNum(); } } class Consumer extends Thread{ Holder holder; public Consumer(String threadName,Holder holder){ super(threadName); this.holder=holder; } public void run(){ holder.subNum(); } } public class TestThread5{ public static void main(String[] args){ Holder one=new Holder(); new Consumer("consumer1",one).start(); new Producer("producer1",one).start(); } } ```

新手请教 关于Java多线程 wait notify的问题

class PrintMsg { public static void main(String[] args) { System.out.println("Hello World!"); Msg m = new Msg(); PutIn in = new PutIn(m); PutOut out = new PutOut(m); Thread t1 = new Thread(in); Thread t2 = new Thread(out); t1.start(); t2.start(); } } class Msg { String name; String sex; boolean flag = false; } class PutIn implements Runnable { Msg r; PutIn(Msg r) { this.r = r; } public void run() { int x = 0; while(true) { synchronized(r) { if(r.flag) try{r.wait();}catch(InterruptedException e){} if(x==0) { r.name = "韩梅梅"; r.sex = "女女女"; } else { r.name = "李雷"; r.sex = "男"; } r.flag = true; r.notify(); } x = (x+1)%2; } } } class PutOut implements Runnable { Msg r; PutOut(Msg r) { this.r = r; } public void run() { while(true) { synchronized(r) { if(!r.flag) try{r.wait();}catch(InterruptedException e){} System.out.println(r.name+"......"+r.sex); r.flag = false; r.notify(); } } } } 问题: 1.class Msg已经定义flag为false. 那class PutIn中 if(r.flag)和class PutOut中的if(!r.flag)是什么意思呢? 2.PutIn中的r.notify();是不是唤醒的是PutOut中的线程? 3.大括号的书写规范吗? 是不是有些地方不需要另起一行? 4.try catch的书写也不规范?

Java多线程synchronized、wait和notify问题

废话不多说,直接粘测试代码 ``` public class Test{ public static void main(String[] args) { try { ThreadB tb = new ThreadB(); tb.start(); System.out.println("0"); synchronized (tb) { System.out.println("3"); tb.wait(); System.out.println("4"); } } catch (InterruptedException e) { e.printStackTrace(); } } } ``` ``` public class ThreadB extends Thread { @Override public void run() { synchronized (this) { System.out.println("1"); notify(); System.out.println("2"); } } } ``` 为什么输出结果 有时候是: 0 1 2 3 有时候是: 0 1 2 3 4

java多线程如何让一个线程只执行一次?

java多线程如何让一个线程只执行一次?我目前只能是检测到getname()然后用wait()方法。想知道还有没其他方法? ``` public class TicketSale { public static void main(String[] args) { Runnable r1=new Ticket(); Thread t1=new Thread(r1); Thread t2=new Thread(r1); Thread t3=new Thread(r1); t1.setName("黄牛党"); t2.setName("桃跑跑"); t3.setName("张票票"); t1.start(); t2.start(); t3.start(); } } class Ticket implements Runnable{ private int ticket=10; private int num=1; public synchronized void sale(){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(ticket>0){ System.out.println(Thread.currentThread().getName()+"抢到第"+(num++)+ "张票。剩余"+((ticket--)-1)+"张票。"); } if(ticket==0){ notify(); System.out.println("票已全部售完"); } if("黄牛党".equals(Thread.currentThread().getName())){ Thread.currentThread().interrupted(); } } @Override public void run() { while(num<10){ sale(); } } } ```

Java中线程wait是如何实现微秒级别识别外界的唤醒动作的

一直以来都惊奇于java是如何实现微秒级别唤醒一个处于wait状态的线程的,今天我通过下面的 程序测试了一下,主线程从调用 notify 到唤醒一个处于 wait 状态的子线程,之间的时间间隔小 于7微秒,这是一个非常短的时间,想知道java在这方面的底层实现原理是什么,有没有其他类似的 的工具也能实现这种耗时非常短的协调交互功能? 为什么想了解这个呢,因为我最近想做个在分布式环境下线程互相协调的工具,其中一个基础功 能需要让一个线程能尽快识别其他线程对临界资源的更新,因为不再是单JVM环境了,所以无法使用线程临界区的 notify, wait 机制快速唤醒另外一个等待的线程了,在分布式环境下,希望一个处于等待状态的线程通过自旋等待的方式尽快识别临界区资源的变动,用 while + sleep 方式还是延迟太大了,希望能从 wait + notify 的实现原理中找下思路,或者各位有更好的推荐方案也行。 下面是我测试 wait , notify 时间间隔的代码,有兴趣的可以看下: public class TestThreadWait { public static void main(String[] args) { Object lock = new Object(); T1 thread = new T1(lock); thread.start(); try { Thread.sleep(500); } catch (InterruptedException e1) { e1.printStackTrace(); } long time1 = 0l; long time2 = 0l; synchronized(lock) { time1 = System.nanoTime(); lock.notify(); time2 = System.nanoTime(); } System.out.println("main thread notify time info : time1 = " + time1 + ", time2 = " + time2 + ", cost : " + (time2-time1)); } static class T1 extends Thread { private Object lock; public T1(Object lock) { this.lock = lock; } public void run() { long time1 = 0l; long time2 = 0l; synchronized(this.lock) { try { time1 = System.nanoTime(); this.lock.wait(); time2 = System.nanoTime(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("thread wait time info : time1 = " + time1 + ", time2 = " + time2 + ", cost : " + (time2-time1)); } } }

java NIO 多线程

<div class="iteye-blog-content-contain" style="font-size: 14px;"> <pre name="code" class="java">public void run() { exitRequest = false ; while( !exitRequest) { try { // 初期化 socketChannel = SocketChannel.open() ; selector = Selector.open() ; socketChannel.socket().setReuseAddress( true) ; socketChannel.configureBlocking( false) ; socketChannel.socket().setReceiveBufferSize( RECV_BUFFER) ; selectionKey = socketChannel.register( selector, SelectionKey.OP_CONNECT) ; selectionKey.attach( new SocketNioControl( notifyObject, selector, socketChannel, selectionKey)) ; socketChannel.connect( inetAddress) ; int timer = 0 ; while( !socketChannel.isConnected()) { selector.select(100) ; if( exitRequest) { break ; } for( SelectionKey key : selector.selectedKeys()) { if( key.isConnectable()) { SocketChannel socketChannel = ( SocketChannel)key.channel() ; SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; socketChannel.finishConnect() ; key.interestOps( SelectionKey.OP_READ) ; socketControl.connect() ; break ; } } if( timer &gt;= TIMER_CONNECT * 1000) { throw new ConnectException() ; } timer += 100 ; } try { while( !exitRequest) { selector.select() ; for( SelectionKey key : selector.selectedKeys()) { SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; if( key.isReadable()) { socketControl.read() ; } if( key.isWritable()) { socketControl.write() ; } } } } catch ( ConnectException ioex) { } catch ( CancelledKeyException ckex) { } } catch ( UnknownHostException uhex) { ErrorMessage.logging( uhex) ; } catch ( Exception ex) { ErrorMessage.logging( ex) ; } finally { try { for( SelectionKey key : selector.keys()) { SocketNioControl socketControl = ( SocketNioControl)key.attachment() ; socketControl.disconnect() ; } if( selector != null) { selector.close() ; selector = null ; } for( int timer = 0; timer &lt; TIMER_RETRY * 1000; timer += 100) { Thread.sleep( 100) ; if( exitRequest) { break ; } } } catch( IOException ioe) { } catch( InterruptedException iex) { } } } }</pre> <p> 线程一直被占用,导致系统hungup.是哪里出问题呢?另外<span style="font-family: monospace; font-size: 1em; line-height: 1.5;"> selector.select() 的值一直是0;</span><span style="font-family: monospace; font-size: 1em; line-height: 1.5;">这一句是起什么作用的?</span></p> </div>

java多线程实例锁问题

1.我在一个方法里面加了两个锁,锁对象分别 是两个实例, 有一个实例会将本实例的线程挂起, 按理说另就只会执行另外一个同步代码块里的内容, 真实情况是两个都已经挂起了, 我的理解是只有锁对象是类class才会两个都挂起, ``` class Customer implements Runnable{ Product p; Product p1; public Customer(Product p,Product p1){ this.p = p; this.p1= p1; } public Customer(Product p){ this.p = p; } @Override public void run() { while(true){ System.out.println("我是消费者被执行了"); synchronized (p1) { System.out.println(p1); System.out.println("hellll"); try { Thread.sleep(222); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } synchronized (p) { if(p.flag){ System.out.println("消费了"+p.name+"价格:"+p.price); // p.flag=false; p.notify(); }else { try { Thread.sleep(1333); p.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } Thread cus1 = new Thread(customer1); cus1.start(); ```

JAVA多线程同步的问题

public class Test { public static void main(String[] args) { Person p = new Person(); ThreadGetPerson tg = new ThreadGetPerson(); tg.setP(p); ThreadSetPerson tp = new ThreadSetPerson(); tp.setP(p); new Thread(tg).start(); new Thread(tp).start(); new Thread(tg).start(); new Thread(tp).start(); } ThreadSetPerson类{ this.p=p; public void run() { boolean flag =true; int i=100; 循环 while(i>0){ 同步 synchronized (p) { if(p.flag){ if(flag){ p.setName(Thread.currentThread().getName()+"AAAAAAA:"+i); p.setSex("男"); p.flag=false; flag=false; }else{ p.setName(Thread.currentThread().getName()+"BBB:"+i); p.setSex("女"); p.flag=false; flag=true; } p.notify(); }else{ p.wait(); } 循环最后 i-- ThreadGetPerson类{ this.p=p; public void run() { int i=100; 循环 while(i>0){ synchronized (p) { if(p.flag){ p.wait(); }else{ System.out.println(p.getName()+"性别为:"+p.getSex()); p.flag=true; p.notify(); } } i--; } 大致就是上面的意思,两个线程赋值,两个线程输出,为什么会出现下面的结果呢? Thread-1AAAAAAA:100性别为:男 Thread-3AAAAAAA:100性别为:男 Thread-1BBB:99性别为:女 Thread-3BBB:98性别为:女 Thread-1AAAAAAA:97性别为:男 就这些每次都不一样,程序线程全部进入wait()能理解,可是为什么会1,3线程都赋值了100呢?两个性别为女的BB,数值间隔只是1. 这结果明明表示1,3线程同时进入了同步代码块吗? 已经同步了的,而且都是一个对象p。 求大神回答

多线程练习小问题 为什么这题notify不起作用

想要用多线程打印出12A34B56C78D....... 但是像这样写只能打出12,notify没有起作用,请问如何改动 ``` public class 作业2 { public static void main(String[] args) { // TODO Auto-generated method stub new Thread(new Number()).start(); new Thread(new Letter()).start(); } } class Number implements Runnable { private int n = 1; @Override public synchronized void run() { for (int i = 0; i < 52; i++) { if (i % 2 == 0 && i != 0) { try { notify();; this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.print(n + i); } } } class Letter implements Runnable { char a = 'a'; @Override public synchronized void run() { try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } for (int i = 0; i < 26; i++) { System.out.print(a + i); try { notify(); this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } ```

java的多线程买票问题,结果出现负数情况

java的多线程买票问题,结果出现负数情况 如果线程为前面两个会出现票号为“0”的情况,如果线程大于2个的话,就会出现负数,请教该如果解决问题呢? [code="java"] public class myFirst { public static void main(String[] args) { Q q = new Q(); new Thread(new SaleS(q)).start();//取单号票 new Thread(new SaleD(q)).start();//取双号票 new Thread(new SaleS(q)).start();//取单号票 new Thread(new SaleD(q)).start();//取双号票 new Thread(new SaleS(q)).start();//取单号票 } } class Q { private int tickets = 10; public synchronized int get() { return tickets; } public synchronized void sale() { if(tickets>0) { System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); try { Thread.sleep(100); } catch(InterruptedException e){} } } public synchronized void sale(boolean b) { if(tickets>0) { if((b && tickets % 2 ==1) || (!b && tickets % 2 ==0)) { try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } /*try { Thread.sleep(1000); } catch(InterruptedException e){}*/ System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); notify(); } } public synchronized void saleSingle() { if(tickets>0) { if(tickets % 2 ==0) { System.out.println(Thread.currentThread().getName()+ " is waitting "); try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); notify(); } } public synchronized void saleDouble() { if(tickets>0) { if(tickets % 2 ==1) { System.out.println(Thread.currentThread().getName()+ " is waitting "); try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); notify(); } } } class SaleS implements Runnable { Q q = null; public SaleS(Q q) {this.q = q;} public void run() { while(q.get()>0) { q.saleSingle(); } } } class SaleD implements Runnable { Q q = null; public SaleD(Q q) {this.q = q;} public void run() { while(q.get()>0) { q.saleDouble(); } } } [/code]

java的多线程问题,结果出现负数情况

预想实现轮番取[color=red]单数[/color]票和[color=red]双号[/color]票的多线程出票过程 执行结果发现: 如果只执行两个进程,程序会卖出票号为“0”的票,如果再增加出票的线程就出现线程为[color=red]负[/color]数的情况了 [code="java"] public class myFirst { public static void main(String[] args) { Q q = new Q(); new Thread(new SaleS(q)).start(); new Thread(new SaleD(q)).start(); new Thread(new SaleS(q)).start(); new Thread(new SaleD(q)).start(); } } class Q { private int tickets = 10; public synchronized int get() { return tickets; } public synchronized void saleSingle() { if(tickets>0) { if(tickets % 2 ==0) { try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } try { Thread.sleep(1000); } catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); notify(); } } public synchronized void saleDouble() { if(tickets>0) { if(tickets % 2 ==1) { try { wait(); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } try { Thread.sleep(1000); } catch(InterruptedException e){} System.out.println(Thread.currentThread().getName()+ " is salling ticket "+ tickets--); notify(); } } } class SaleS implements Runnable { Q q = null; public SaleS(Q q) {this.q = q;} public void run() { while(q.get()>=1) { q.saleSingle(); } } } class SaleD implements Runnable { Q q = null; public SaleD(Q q) {this.q = q;} public void run() { while(q.get()>=2) { q.saleDouble(); } } } [/code]

新手 Java 多线程

多线程 obj是一个对象 如果A线程调用了 obj.wait() ,是不是要 B(其他)线程调用 obj.notify() 才能醒来

多线程wait()与notify()的一点疑惑

# ## # **若有多个线程因wait()而阻塞,通知notify()个数等于或大于wait()个数就一定能都通知到吗?PS:是同一个对象锁** 希望大神能给出确定答案,最好有证明,不胜感激

Java多线程,生产消费问题

package thread; public class Producer_ConsumerTest { public static void main(String[] args) { SyncStack ss = new SyncStack(); Thread producter = new Producter(ss); Thread consumer = new Consumer(ss); producter.start(); consumer.start(); } } class SyncStack { private int total = 0; private boolean flag = false; synchronized void product() { while(flag == true) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } total++; flag = true; this.notify(); } synchronized int conmuse() { while(flag == false) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } total--; flag = false; this.notify(); return total; } } class Producter extends Thread { SyncStack ss; Producter(SyncStack ss) { this.ss = ss; } public void run() { for(int i=1;i<10;i++) { ss.product(); System.out.println("生产者" + Thread.currentThread().getName() + "生产了第" + i + "个商品,商品总数为"); } } } class Consumer extends Thread { SyncStack ss; Consumer(SyncStack ss) { this.ss = ss; } public void run() { for(int i=1;i<10;i++) { ss.conmuse(); System.out.println("消费者" + Thread.currentThread().getName() + "消费了第" + i + "个商品总数为"); } } } ----------------- [b]我希望的输出结果是生产1个,然后消费1个,生产在前,但是达不到要求,目前实际输出是无序的,哪位朋友能帮忙修改一下吗?[/b]

关于线程的notify

notify是叫醒一个在当前对象wait的线程 那么如果我当前对象有3个线程 我想叫醒我要指定的一个线程怎么办 而notify没有穿参

Java中关于原子变量和多线程安全问题

自学java碰到些问题,向各位大佬们请教下 多线程安全问题产生的前提 是不是 多线程对共享数据进行了非原子操作 既然是共享数据进行非原子性操作的化,那用AtomicXxx类应该能解决吧 但是.... ``` package Thread_01; import java.util.concurrent.atomic.AtomicInteger; class TicketSale2 implements Runnable{ //private int tickets=100; AtomicInteger tickets=new AtomicInteger(10); Object object=new Object(); //线程任务为售票,所以将该任务在run方法中执行 public void run(){ while(true) { //synchronized (object) { if(tickets.get()>0) { try { Thread.sleep(20); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"您好,您的票号为"+tickets.getAndDecrement()); } else{break;} //} } } } public class TicketDemo3 { public static void main(String[] args) { //线程任务对象 TicketSale2 ticketSale=new TicketSale2(); //线程对象 Thread t1=new Thread(ticketSale); Thread t2=new Thread(ticketSale); Thread t3=new Thread(ticketSale); Thread t4=new Thread(ticketSale); t1.start(); t2.start(); t3.start(); t4.start(); } } ``` 还是会产生线程安全问题...这是为什么呢 还望大佬们抽空解答下 ![图片说明](https://img-ask.csdn.net/upload/201901/12/1547275181_286997.png)

新手 Java 多线程 .wait(); 函数前面的对象 要填什么

![图片说明](https://img-ask.csdn.net/upload/201809/19/1537347235_194229.jpg) .wait() 的作用是 让当前线程进入等待状态,同时释放当前线程所持有的锁。 那 .wait前面的对象要填什么

java jdk 8 帮助文档 中文 文档 chm 谷歌翻译

JDK1.8 API 中文谷歌翻译版 java帮助文档 JDK API java 帮助文档 谷歌翻译 JDK1.8 API 中文 谷歌翻译版 java帮助文档 Java最新帮助文档 本帮助文档是使用谷

软件测试2小时入门

本课程内容系统、全面、简洁、通俗易懂,通过2个多小时的介绍,让大家对软件测试有个系统的理解和认识,具备基本的软件测试理论基础。 主要内容分为5个部分: 1 软件测试概述,了解测试是什么、测试的对象、原则、流程、方法、模型;&nbsp; 2.常用的黑盒测试用例设计方法及示例演示;&nbsp; 3 常用白盒测试用例设计方法及示例演示;&nbsp; 4.自动化测试优缺点、使用范围及示例‘;&nbsp; 5.测试经验谈。

汽车行驶工况构建2019 D题.zip

1. 标记0与0之间的片段位置 2.标记所之间的毛刺数的位置 3.去掉毛刺数据 速度 并生成 新的数组 4.标记时间段 5. 0与0之间 如果有不连续的时间片段 置零 先找到时间间隔 再看间隔时间对应

Python+OpenCV计算机视觉

Python+OpenCV计算机视觉系统全面的介绍。

面试了一个 31 岁程序员,让我有所触动,30岁以上的程序员该何去何从?

最近面试了一个31岁8年经验的程序猿,让我有点感慨,大龄程序猿该何去何从。

专为程序员设计的数学课

<p> 限时福利限时福利,<span>15000+程序员的选择!</span> </p> <p> 1、原价 115 元,限时特价仅需 49 元!<br> 2、购课后添加学习助手(微信号:csdnxy68),按提示消息领取编程大礼包!并获取讲师答疑服务! </p> <p> <br> </p> <p> 套餐中一共包含5门程序员必学的数学课程(共47讲) </p> <p> 课程1:《零基础入门微积分》 </p> <p> 课程2:《数理统计与概率论》 </p> <p> 课程3:《代码学习线性代数》 </p> <p> 课程4:《数据处理的最优化》 </p> <p> 课程5:《马尔可夫随机过程》 </p> <p> <br> </p> <p> 哪些人适合学习这门课程? </p> <p> 1)大学生,平时只学习了数学理论,并未接触如何应用数学解决编程问题; </p> <p> 2)对算法、数据结构掌握程度薄弱的人,数学可以让你更好的理解算法、数据结构原理及应用; </p> <p> 3)看不懂大牛代码设计思想的人,因为所有的程序设计底层逻辑都是数学; </p> <p> 4)想学习新技术,如:人工智能、机器学习、深度学习等,这门课程是你的必修课程; </p> <p> 5)想修炼更好的编程内功,在遇到问题时可以灵活的应用数学思维解决问题。 </p> <p> <br> </p> <p> 在这门「专为程序员设计的数学课」系列课中,我们保证你能收获到这些:<br> <br> <span> </span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">①价值300元编程课程大礼包</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">②应用数学优化代码的实操方法</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">③数学理论在编程实战中的应用</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">④程序员必学的5大数学知识</span> </p> <p class="ql-long-24357476"> <span class="ql-author-24357476">⑤人工智能领域必修数学课</span> </p> <p> <br> 备注:此课程只讲程序员所需要的数学,即使你数学基础薄弱,也能听懂,只需要初中的数学知识就足矣。<br> <br> 如何听课? </p> <p> 1、登录CSDN学院 APP 在我的课程中进行学习; </p> <p> 2、登录CSDN学院官网。 </p> <p> <br> </p> <p> 购课后如何领取免费赠送的编程大礼包和加入答疑群? </p> <p> 购课后,添加助教微信:<span> csdnxy68</span>,按提示领取编程大礼包,或观看付费视频的第一节内容扫码进群答疑交流! </p> <p> <img src="https://img-bss.csdn.net/201912251155398753.jpg" alt=""> </p>

微信公众平台开发入门

本套课程的设计完全是为初学者量身打造,课程内容由浅入深,课程讲解通俗易懂,代码实现简洁清晰。通过本课程的学习,学员能够入门微信公众平台开发,能够胜任企业级的订阅号、服务号、企业号的应用开发工作。 通过本课程的学习,学员能够对微信公众平台有一个清晰的、系统性的认识。例如,公众号是什么,它有什么特点,它能做什么,怎么开发公众号。 其次,通过本课程的学习,学员能够掌握微信公众平台开发的方法、技术和应用实现。例如,开发者文档怎么看,开发环境怎么搭建,基本的消息交互如何实现,常用的方法技巧有哪些,真实应用怎么开发。

4小时玩转微信小程序——基础入门与微信支付实战

这是一个门针对零基础学员学习微信小程序开发的视频教学课程。课程采用腾讯官方文档作为教程的唯一技术资料来源。杜绝网络上质量良莠不齐的资料给学员学习带来的障碍。 视频课程按照开发工具的下载、安装、使用、程序结构、视图层、逻辑层、微信小程序等几个部分组织课程,详细讲解整个小程序的开发过程

Java基础知识面试题(2020最新版)

文章目录Java概述何为编程什么是Javajdk1.5之后的三大版本JVM、JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码?采用字节码的最大好处是什么什么是Java程序的主类?应用程序和小程序的主类有何不同?Java应用程序与小程序之间有那些差别?Java和C++的区别Oracle JDK 和 OpenJDK 的对比基础语法数据类型Java有哪些数据类型switc...

IE主页被篡改修复

IE主页修复。IE主页被篡改修复。一键修复IE主页

我说我不会算法,阿里把我挂了。

不说了,字节跳动也反手把我挂了。

土豆SDK(Java版)-非官方

由于土豆SDK一直建设中,最近几天抽空写了一套java的SDK。包含了现有的所有请求协议。本套SDK中仅提供了oAuth的方式(引用oAuth.net的java版示例),并没有在框架中实现,涉及到登录

Java8零基础入门视频教程

这门课程基于主流的java8平台,由浅入深的详细讲解了java SE的开发技术,可以使java方向的入门学员,快速扎实的掌握java开发技术!

【数据结构与算法综合实验】欢乐连连看(C++ & MFC)案例

这是武汉理工大学计算机学院数据结构与算法综合实验课程的第三次项目:欢乐连连看(C++ & MFC)迭代开发代码。运行环境:VS2017。已经实现功能:开始游戏、消子、判断胜负、提示、重排、计时、帮助。

数学建模竞赛D题“汽车行驶工况构建

第十六届“华为杯”数学建模竞赛D题“汽车行驶工况构建”论文。论文获得比赛国家二等奖,论文为原创,仅供参考。 关键词:数据处理;降维;聚类。

Vue.js 2.0之全家桶系列视频课程

基于新的Vue.js 2.3版本, 目前新全的Vue.js教学视频,让你少走弯路,直达技术前沿! 1. 包含Vue.js全家桶(vue.js、vue-router、axios、vuex、vue-cli、webpack、ElementUI等) 2. 采用笔记+代码案例的形式讲解,通俗易懂

Android音视频开发全套

Android平台音视频开发全套,涉及:FFmpeg软解码解码、Mediacodec硬解码编码、Openssl音频播放、OpenGL ES视频渲染、RTMP推流等核心重要知识点。

设计模式(JAVA语言实现)--20种设计模式附带源码

课程亮点: 课程培训详细的笔记以及实例代码,让学员开始掌握设计模式知识点 课程内容: 工厂模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、原型模型、代理模式、单例模式、适配器模式 策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式 课程特色: 笔记设计模式,用笔记串连所有知识点,让学员从一点一滴积累,学习过程无压力 笔记标题采用关键字标识法,帮助学员更加容易记住知识点 笔记以超链接形式让知识点关联起来,形式知识体系 采用先概念后实例再应用方式,知识点深入浅出 提供授课内容笔记作为课后复习以及工作备查工具 部分图表(电脑PC端查看):

极简JAVA学习营第四期(报名以后加助教微信:eduxy-1)

想学好JAVA必须要报两万的培训班吗? Java大神勿入 如果你: 零基础想学JAVA却不知道从何入手 看了一堆书和视频却还是连JAVA的环境都搭建不起来 囊中羞涩面对两万起的JAVA培训班不忍直视 在职没有每天大块的时间专门学习JAVA 那么恭喜你找到组织了,在这里有: 1. 一群志同道合立志学好JAVA的同学一起学习讨论JAVA 2. 灵活机动的学习时间完成特定学习任务+每日编程实战练习 3. 热心助人的助教和讲师及时帮你解决问题,不按时完成作业小心助教老师的家访哦 上一张图看看前辈的感悟: &nbsp; &nbsp; 大家一定迫不及待想知道什么是极简JAVA学习营了吧,下面就来给大家说道说道: 什么是极简JAVA学习营? 1. 针对Java小白或者初级Java学习者; 2. 利用9天时间,每天1个小时时间; 3.通过 每日作业 / 组队PK / 助教答疑 / 实战编程 / 项目答辩 / 社群讨论 / 趣味知识抢答等方式让学员爱上学习编程 , 最终实现能独立开发一个基于控制台的‘库存管理系统’ 的学习模式 极简JAVA学习营是怎么学习的? &nbsp; 如何报名? 只要购买了极简JAVA一:JAVA入门就算报名成功! &nbsp;本期为第四期极简JAVA学习营,我们来看看往期学员的学习状态: 作业看这里~ &nbsp; 助教的作业报告是不是很专业 不交作业打屁屁 助教答疑是不是很用心 &nbsp; 有奖抢答大家玩的很嗨啊 &nbsp; &nbsp; 项目答辩终于开始啦 &nbsp; 优秀者的获奖感言 &nbsp; 这是答辩项目的效果 &nbsp; &nbsp; 这么细致的服务,这么好的氛围,这样的学习效果,需要多少钱呢? 不要1999,不要199,不要99,只要9.9 是的你没听错,只要9.9以上所有就都属于你了 如果你: 1、&nbsp;想学JAVA没有基础 2、&nbsp;想学JAVA没有整块的时间 3、&nbsp;想学JAVA没有足够的预算 还等什么?赶紧报名吧,抓紧抢位,本期只招300人,错过只有等时间待定的下一期了 &nbsp; 报名请加小助手微信:eduxy-1 &nbsp; &nbsp;

2019 AI开发者大会

2019 AI开发者大会(AI ProCon 2019)是由中国IT社区CSDN主办的AI技术与产业年度盛会。多年经验淬炼,如今蓄势待发:2019年9月6-7日,大会将有近百位中美顶尖AI专家、知名企业代表以及千余名AI开发者齐聚北京,进行技术解读和产业论证。我们不空谈口号,只谈技术,诚挚邀请AI业内人士一起共铸人工智能新篇章!

web网页制作期末大作业

分享思维,改变世界. web网页制作,期末大作业. 所用技术:html css javascript 分享所学所得

手把手实现Java图书管理系统(附源码)

【超实用课程内容】 本课程演示的是一套基于Java的SSM框架实现的图书管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的java人群。详细介绍了图书管理系统的实现,包括:环境搭建、系统业务、技术实现、项目运行、功能演示、系统扩展等,以通俗易懂的方式,手把手的带你从零开始运行本套图书管理系统,该项目附带全部源码可作为毕设使用。 【课程如何观看?】 PC端:https://edu.csdn.net/course/detail/27513 移动端:CSDN 学院APP(注意不是CSDN APP哦) 本课程为录播课,课程2年有效观看时长,大家可以抓紧时间学习后一起讨论哦~ 【学员专享增值服务】 源码开放 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 下载方式:电脑登录https://edu.csdn.net/course/detail/27513,点击右下方课程资料、代码、课件等打包下载

MySQL数据库面试题(2020最新版)

文章目录数据库基础知识为什么要使用数据库什么是SQL?什么是MySQL?数据库三大范式是什么mysql有关权限的表都有哪几个MySQL的binlog有有几种录入格式?分别有什么区别?数据类型mysql有哪些数据类型引擎MySQL存储引擎MyISAM与InnoDB区别MyISAM索引与InnoDB索引的区别?InnoDB引擎的4大特性存储引擎选择索引什么是索引?索引有哪些优缺点?索引使用场景(重点)...

2019 Python开发者日-培训

本次活动将秉承“只讲技术,拒绝空谈”的理念,邀请十余位身处一线的Python技术专家,重点围绕Web开发、自动化运维、数据分析、人工智能等技术模块,分享真实生产环境中使用Python应对IT挑战的真知灼见。此外,针对不同层次的开发者,大会还安排了深度培训实操环节,为开发者们带来更多深度实战的机会。

C++语言基础视频教程

C++语言基础视频培训课程:本课与主讲者在大学开出的程序设计课程直接对接,准确把握知识点,注重教学视频与实践体系的结合,帮助初学者有效学习。本教程详细介绍C++语言中的封装、数据隐藏、继承、多态的实现等入门知识;主要包括类的声明、对象定义、构造函数和析构函数、运算符重载、继承和派生、多态性实现等。 课程需要有C语言程序设计的基础(可以利用本人开出的《C语言与程序设计》系列课学习)。学习者能够通过实践的方式,学会利用C++语言解决问题,具备进一步学习利用C++开发应用程序的基础。

零基础学C#编程—C#从小白到大咖

本课程从初学者角度出发,提供了C#从入门到成为程序开发高手所需要掌握的各方面知识和技术。 【课程特点】 1 由浅入深,编排合理; 2 视频讲解,精彩详尽; 3 丰富实例,轻松易学; 4 每章总结配有难点解析文档。 15大章节,228课时,1756分钟与你一同进步!

编程实现学生基本信息管理程序

编程实现学生基本信息管理程序。学生基本信息包括:学号、姓名、性别、年龄、班级、学院、专业等。具体实现的管理功能如下: (1) 输入并显示多个学生的基本信息; (2) 可根据需要实现学生信息的添加; (

android 漂亮的UI界面 完整的界面设计

声明:这也是我学习时在网上下载的,鉴于分享精神,并且觉得很不错才上传上来的。。。。。 android 漂亮的UI界面 完整的界面设计 这是一个完整的UI设计,但是没写动作,这是一个公司程序员的公司任务

Anaconda详细安装及使用教程(带图文)

Anacond的介绍 Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。 因为包含了大量的科学包,Anaconda 的下载文件比较大(约 531 MB),如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版(仅包含conda和 Python)。 Conda是一个开源的包、环境管理器,可以用于...

DirectX修复工具V4.0增强版

DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复

相关热词 c# 解析cad c#数字格式化万 c#int转byte c#格式化日期 c# wpf 表格 c# 实现ad域验证登录 c#心跳包机制 c#使用fmod.dll c#dll vb 调用 c# outlook
立即提问
相关内容推荐