java线程条件变量_使用条件变量(多线程笔记)

条件变量属性:

使用条件变量可以以原子方式阻塞线程,知道某个特定条件为真为止。条件变量始终与互斥锁一起使用。

使用条件变量,线程可以以原子方式阻塞,知道满足某个条件为止。对掉件的测试时在互斥锁的保护下进行的。

如果条件为假,县城通常会给予条件变量则阻塞,并于原子方式释放等待条件变化的互斥锁。如果一个线程更改了条件,该线程可能会向相关的条件变量发出信号,从而是一个或多个等待的线程执行以下操作:

唤醒

再次获取互斥锁

重新评估条件

以下情况下,条件变量可用于在进程之间同步线程:

线程是在可以写入的内存中分配的

内存由协作进程共享

调度策略可确定唤醒阻塞线程的方式,对于缺省值,按照优先级顺序唤醒线程。

必须设置和初始化条件变量的属性,然后才能使用条件变量。

初始化条件变量属性:

使用pthread_condattr_init(3C) 可以将与该对象相关联的属性初始化为其缺省值。在执行过程中,线程系统会为每个属性对象分配存储空间。

pthread_condattr_init语法

int pthread_cond_init(pthread_cond_t *ptr  , const othread_condattr_t *av);

cattr 设置为NULL。将cattr 设置为NULL 与传递缺省条件变量属性对象的地址等效,但是

没有内存开销。

使用PTHREAD_COND_INITIALIZER 宏可以将以静态方式定义的条件变量初始化为其缺省

属性。PTHREAD_COND_INITIALIZER宏与动态分配具有null 属性的pthread_cond_init()

等效,但是不进行错误检查。

多个线程决不能同时初始化或重新初始化同一个条件变量。如果要重新初始化或销毁

某个条件变量,则应用程序必须确保该条件变量未被使用。

pthread_cond_init返回值

pthread_cond_init()在成功完成之后会返回零。其他任何返回值都表示出现了错误。

如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述: cattr 指定的值无效。

EBUSY

描述: 条件变量处于使用状态。

EAGAIN

描述: 必要的资源不可用。

ENOMEM

描述: 内存不足,无法初始化条件变量。

基于条件变量阻塞

使用pthread_cond_wait(3C)可以以原子方式释放mp 所指向的互斥锁,并导致调用线

程基于cv 所指向的条件变量阻塞。

pthread_cond_wait 语法

int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex);

1

2

#include pthread_cond_t cv;

pthread_mutex_t mp;int ret;

/* wait on condition variable */ret = pthread_cond_wait(&cv, &mp);

阻塞的线程可以通过pthread_cond_signal() 或pthread_cond_broadcast()唤醒,也可

以在信号传送将其中断时唤醒。

不能通过pthread_cond_wait() 的返回值来推断与条件变量相关联的条件的值的任何变

化。必须重新评估此类条件。

pthread_cond_wait()例程每次返回结果时调用线程都会锁定并且拥有互斥锁,即使返

回错误时也是如此。

该条件获得信号之前,该函数一直被阻塞。该函数会在被阻塞之前以原子方式释放相

关的互斥锁,并在返回之前以原子方式再次获取该互斥锁。

通常,对条件表达式的评估是在互斥锁的保护下进行的。如果条件表达式为假,线程

会基于条件变量阻塞。然后,当该线程更改条件值时,另一个线程会针对条件变量发

出信号。这种变化会导致所有等待该条件的线程解除阻塞并尝试再次获取互斥锁。

必须重新测试导致等待的条件,然后才能从pthread_cond_wait()处继续执行。唤醒的

线程重新获取互斥锁并从pthread_cond_wait()返回之前,条件可能会发生变化。等待

线程可能并未真正唤醒。建议使用的测试方法是,将条件检查编写为调用

pthread_cond_wait() 的while()循环。

pthread_mutex_lock();

while(condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();

如果有多个线程基于该条件变量阻塞,则无法保证按特定的顺序获取互斥锁。

注– pthread_cond_wait() 是取消点。如果取消处于暂挂状态,并且调用线程启用了取

消功能,则该线程会终止,并在继续持有该锁的情况下开始执行清除处理程序。

pthread_cond_wait 返回值

pthread_cond_wait()在成功完成之后会返回零。其他任何返回值都表示出现了错误。

如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 或mp 指定的值无效。

解除阻塞一个线程

对于基于cv 所指向的条件变量阻塞的线程,使用pthread_cond_signal(3C)可以解除阻

塞该线程。

pthread_cond_signal语法

int pthread_cond_signal(pthread_cond_t *cv);

1

2

#include pthread_cond_t cv;int ret;/* one condition variable is signaled */ret = pthread_cond_signal(&cv);

应在互斥锁的保护下修改相关条件,该互斥锁用于获得信号的条件变量中。否则,可

能在条件变量的测试和pthread_cond_wait()阻塞之间修改该变量,这会导致无限期等

待。

调度策略可确定唤醒阻塞线程的顺序。对于SCHED_OTHER,将按优先级顺序唤醒线程。

如果没有任何线程基于条件变量阻塞,则调用pthread_cond_signal() 不起作用。

示例 使用pthread_cond_wait() 和pthread_cond_signal()

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count()

{

pthread_mutex_lock(&count_lock);

while (count == 0)

pthread_cond_wait(&count_nonzero, &count_lock);

count = count - 1;

pthread_mutex_unlock(&count_lock);

}

increment_count()

{

pthread_mutex_lock(&count_lock);

if (count == 0)

pthread_cond_signal(&count_nonzero);

count = count + 1;

pthread_mutex_unlock(&count_lock);

}

pthread_cond_signal返回值

pthread_cond_signal()在成功完成之后会返回零。其他任何返回值都表示出现了错

误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 指向的地址非法。

示例 说明了如何使用pthread_cond_wait()和pthread_cond_signal()。

在指定的时间之前阻塞

pthread_cond_timedwait(3C) 的用法与pthread_cond_wait()的用法基本相同,区别在

于在由abstime 指定的时间之后pthread_cond_timedwait()不再被阻塞。

pthread_cond_timedwait语法

int pthread_cond_timedwait(pthread_cond_t *cv,

pthread_mutex_t *mp, const struct timespec *abstime);

1

2

3

#include #include pthread_cond_t cv;

pthread_mutex_t mp;

timestruct_t abstime;int ret;/* wait on condition variable */ret = pthread_cond_timedwait(&cv, &mp, &abstime);

1

2

3

4

5

6

7

8

9

pthread_cond_timewait()每次返回时调用线程都会锁定并且拥有互斥锁,即使

pthread_cond_timedwait()返回错误时也是如此。

pthread_cond_timedwait() 函数会一直阻塞,直到该条件获得信号,或者最后一个参数

所指定的时间已过为止。

注– pthread_cond_timedwait()也是取消点。

示例计时条件等待

pthread_timestruc_t to;

pthread_mutex_t m;

pthread_cond_t c;

...

pthread_mutex_lock(&m);

to.tv_sec = time(NULL) + TIMEOUT;

to.tv_nsec = 0;

while (cond == FALSE) {

err = pthread_cond_timedwait(&c, &m, &to);

if (err == ETIMEDOUT) {

/* timeout, do something */

break;

}

}

pthread_mutex_unlock(&m);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

pthread_cond_timedwait 返回值

pthread_cond_timedwait() 在成功完成之后会返回零。其他任何返回值都表示出现了错

误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 或abstime 指向的地址非法。

ETIMEDOUT

描述: abstime 指定的时间已过。

超时会指定为当天时间,以便在不重新计算值的情况下高效地重新测试条件,如示例

中所示。

8598885.html在指定的时间间隔内阻塞

pthread_cond_reltimedwait_np(3C) 的用法与pthread_cond_timedwait()的用法基本相

同,唯一的区别在于pthread_cond_reltimedwait_np()会采用相对时间间隔而不是将来

的绝对时间作为其最后一个参数的值。

pthread_cond_reltimedwait_np语法

int pthread_cond_reltimedwait_np(pthread_cond_t *cv, pthread_mutex_t *mp,

const struct timespec *reltime);

1

2

3

#include #include pthread_cond_t cv;

pthread_mutex_t mp;

timestruct_t reltime;int ret;/* wait on condition variable */ret = pthread_cond_reltimedwait_np(&cv, &mp, &reltime);

1

2

3

4

5

6

7

8

pthread_cond_reltimedwait_np() 每次返回时调用线程都会锁定并且拥有互斥锁,即使

pthread_cond_reltimedwait_np()返回错误时也是如此。pthread_cond_reltimedwait_np()函数会一直阻塞,直到该条件获得信号,或者最后一个参数指定的时间间隔已过为止。

注– pthread_cond_reltimedwait_np()也是取消点。

pthread_cond_reltimedwait_np返回值

pthread_cond_reltimedwait_np()在成功完成之后会返回零。其他任何返回值都表示出

现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 或reltime 指示的地址非法。

ETIMEDOUT

描述: reltime 指定的时间间隔已过。

8598885.html解除阻塞所有线程

对于基于cv 所指向的条件变量阻塞的线程,使用pthread_cond_broadcast(3C)可以解

除阻塞所有这些线程,这由pthread_cond_wait()来指定。

pthread_cond_broadcast 语法

int pthread_cond_broadcast(pthread_cond_t *cv);

1

2

#include pthread_cond_t cv;int ret;

/* all condition variables are signaled */ret = pthread_cond_broadcast(&cv);

1

2

3

4

5

6

如果没有任何线程基于该条件变量阻塞,则调用pthread_cond_broadcast()不起作

用。

由于pthread_cond_broadcast() 会导致所有基于该条件阻塞的线程再次争用互斥锁,

因此请谨慎使用pthread_cond_broadcast()。例如,通过使用

pthread_cond_broadcast(),线程可在资源释放后争用不同的资源量,如示例 中

所示。

示例条件变量广播

pthread_mutex_t rsrc_lock;

pthread_cond_t rsrc_add;unsigned int resources;

get_resources(int amount)

{

pthread_mutex_lock(&rsrc_lock);

while (resources < amount) {

pthread_cond_wait(&rsrc_add, &rsrc_lock);

}

resources -= amount;

pthread_mutex_unlock(&rsrc_lock);

}

add_resources(int amount)

{

pthread_mutex_lock(&rsrc_lock);

resources += amount;

pthread_cond_broadcast(&rsrc_add);

pthread_mutex_unlock(&rsrc_lock);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

请注意,在add_resources()中,首先更新resources 还是首先在互斥锁中调用

pthread_cond_broadcast()无关紧要。

应在互斥锁的保护下修改相关条件,该互斥锁用于获得信号的条件变量中。否则,可

能在条件变量的测试和pthread_cond_wait()阻塞之间修改该变量,这会导致无限期等

待。

pthread_cond_broadcast 返回值

pthread_cond_broadcast()在成功完成之后会返回零。其他任何返回值都表示出现了错

误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 指示的地址非法。

8598885.html销毁条件变量状态

使用pthread_cond_destroy(3C) 可以销毁与cv 所指向的条件变量相关联的任何状态。

pthread_cond_destroy 语法

int pthread_cond_destroy(pthread_cond_t *cv);

1

2

#include pthread_cond_t cv;int ret;

/* Condition variable is destroyed */ret = pthread_cond_destroy(&cv);

1

2

3

4

5

6

请注意,没有释放用来存储条件变量的空间。

pthread_cond_destroy返回值

pthread_cond_destroy()在成功完成之后会返回零。其他任何返回值都表示出现了错

误。如果出现以下情况,该函数将失败并返回对应的值。

EINVAL

描述: cv 指定的值无效。

8598885.html唤醒丢失问题

如果线程未持有与条件相关联的互斥锁,则调用pthread_cond_signal() 或

pthread_cond_broadcast()会产生唤醒丢失错误。

满足以下所有条件时,即会出现唤醒丢失问题:

■ 一个线程调用pthread_cond_signal()或pthread_cond_broadcast()

■ 另一个线程已经测试了该条件,但是尚未调用pthread_cond_wait()

■ 没有正在等待的线程信号不起作用,因此将会丢失,仅当修改所测试的条件但未持有

与之相关联的互斥锁时,才会出现此问题。只要仅在持有关联的互斥锁同时修改所测试

的条件,即可调用pthread_cond_signal() 和pthread_cond_broadcast(),

而无论这些函数是否持有关联的互斥锁。

8598885.html生成方和使用者问题

并发编程中收集了许多标准的众所周知的问题,生成方和使用者问题只是其中的一个

问题。此问题涉及到一个大小限定的缓冲区和两类线程(生成方和使用者),生成方

将项放入缓冲区中,然后使用者从缓冲区中取走项。

生成方必须在缓冲区中有可用空间之后才能向其中放置内容。使用者必须在生成方向

缓冲区中写入之后才能从中提取内容。

条件变量表示一个等待某个条件获得信号的线程队列。

示例中包含两个此类队列。一个队列(less) 针对生成方,用于等待缓冲区中出现空

位置。另一个队列(more) 针对使用者,用于等待从缓冲槽位的空位置中提取其中包含

的信息。该示例中还包含一个互斥锁,因为描述该缓冲区的数据结构一次只能由一个

线程访问。

示例生成方和使用者的条件变量问题

typedef struct {

char buf[BSIZE];

int occupied;

int nextin;

int nextout;

pthread_mutex_t mutex;

pthread_cond_t more;

pthread_cond_t less;

} buffer_t;

buffer_t buffer;

1

2

3

4

5

6

7

8

9

10

如示例 中所示,生成方线程获取该互斥锁以保护buffer 数据结构,然后,缓冲区

确定是否有空间可用于存放所生成的项。如果没有可用空间,生成方线程会调用

pthread_cond_wait()。pthread_cond_wait()会导致生成方线程连接正在等待less 条件

获得信号的线程队列。less 表示缓冲区中的可用空间。

与此同时,在调用pthread_cond_wait()的过程中,该线程会释放互斥锁的锁定。正在

等待的生成方线程依赖于使用者线程在条件为真时发出信号,如示例 中所示。该

条件获得信号时,将会唤醒等待less 的第一个线程。但是,该线程必须再次锁定互斥

锁,然后才能从pthread_cond_wait()返回。

获取互斥锁可确保该线程再次以独占方式访问缓冲区的数据结构。该线程随后必须检

查缓冲区中是否确实存在可用空间。如果空间可用,该线程会向下一个可用的空位置

中进行写入。

与此同时,使用者线程可能正在等待项出现在缓冲区中。这些线程正在等待条件变量

more。刚在缓冲区中存储内容的生成方线程会调用pthread_cond_signal() 以唤醒下一

个正在等待的使用者。如果没有正在等待的使用者,此调用将不起作用。

最后,生成方线程会解除锁定互斥锁,从而允许其他线程处理缓冲区的数据结构。

示例生成方和使用者问题:生成方

void producer(buffer_t *b, char item)

{

pthread_mutex_lock(&b->mutex);

while (b->occupied >= BSIZE)

pthread_cond_wait(&b->less, &b->mutex);

assert(b->occupied < BSIZE);

b->buf[b->nextin++] = item;

b->nextin %= BSIZE;

b->occupied++;

/* now: either b->occupied < BSIZE and b->nextin is the index

of the next empty slot in the buffer, or

b->occupied == BSIZE and b->nextin is the index of the

next (occupied) slot that will be emptied by a consumer

(such as b->nextin == b->nextout) */

pthread_cond_signal(&b->more);

pthread_mutex_unlock(&b->mutex);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

请注意assert()语句的用法。除非在编译代码时定义了NDEBUG,否则assert() 在其参

数的计算结果为真(非零)时将不执行任何操作。如果参数的计算结果为假(零),

则该程序会中止。在多线程程序中,此类断言特别有用。如果断言失败,assert()会

立即指出运行时问题。assert() 还有另一个作用,即提供有用的注释。

以/* now: either b->occupied ...开头的注释最好以断言形式表示,但是由于语句过

于复杂,无法用布尔值表达式来表示,因此将用英语表示。

断言和注释都是不变量的示例。这些不变量是逻辑语句,在程序正常执行时不应将其

声明为假,除非是线程正在修改不变量中提到的一些程序变量时的短暂修改过程中。

当然,只要有线程执行语句,断言就应当为真。

使用不变量是一种极为有用的方法。即使没有在程序文本中声明不变量,在分析程序

时也应将其视为不变量。

每次线程执行包含注释的代码时,生成方代码中表示为注释的不变量始终为真。如果

将此注释移到紧挨mutex_unlock()的后面,则注释不一定仍然为真。如果将此注释移

到紧跟assert()之后的位置,则注释仍然为真。

因此,不变量可用于表示一个始终为真的属性,除非一个生成方或一个使用者正在更

改缓冲区的状态。线程在互斥锁的保护下处理缓冲区时,该线程可能会暂时声明不变

量为假。但是,一旦线程结束对缓冲区的操作,不变量即会恢复为真。

示例给出了使用者的代码。该逻辑流程与生成方的逻辑流程相对称。

示例生成方和使用者问题:使用者

char consumer(buffer_t *b)

{

char item;

pthread_mutex_lock(&b->mutex);

while(b->occupied <= 0)

pthread_cond_wait(&b->more, &b->mutex);

assert(b->occupied > 0);

item = b->buf[b->nextout++];

b->nextout %= BSIZE;

b->occupied--;

/* now: either b->occupied > 0 and b->nextout is the index

of the next occupied slot in the buffer, or

b->occupied == 0 and b->nextout is the index of the next

(empty) slot that will be filled by a producer (such as

b->nextout == b->nextin) */

pthread_cond_signal(&b->less);

pthread_mutex_unlock(&b->mutex);

return(item);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/520222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用PyTorch创建一个图像分类器?So easy!(Part 2)

在第一部分中&#xff0c;我们知道了为什么以及如何加载预先训练好的神经网络&#xff0c;我们可以用自己的分类器代替已有神经网络的分类器。那么&#xff0c;在这篇文章中&#xff0c;我们将学习如何训练分类器。 训练分类器 首先&#xff0c;我们需要为分类器提供待分类的…

涨姿势,一个通信项目从开始到结束,原来还包括这些工作

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 小枣君责编 | 阿秃本月12日&#xff0c;中国移动31个省的通信工程设计与可行性研究集采正式启动。这次集采规模庞大&#xff0c;涵盖了无线网(5G、FDD、NB等)、核心网、承载网、支撑网等专业方向&#xff0c;预估基本规模超4…

听说支付宝有一个“疯起来连自己都打”的项目

小蚂蚁说&#xff1a; 自古红蓝出CP&#xff0c;在蚂蚁金服就有这样两支“相爱相杀”的队伍——红军和蓝军。蓝军是进攻方&#xff0c;主要职责是挖掘系统的弱点并发起“真实”的攻击&#xff0c;俗称“找茬”&#xff1b;红军则是防守方&#xff0c;其防控体系建设中的实时核…

蚂蚁金服红蓝军技术攻防演练究竟有多“狠”

如果一个技术团队不干别的&#xff0c;专门“搞破坏”&#xff0c;这是一种怎样的存在&#xff1f;这真的不是“天方夜谭”&#xff0c;在支付宝确实有这么一支队伍——技术蓝军。蓝军的任务就是不断地攻击和进攻&#xff0c;而防守方则是技术红军。在支付宝&#xff0c;蓝军从…

阿里巴巴在内蒙古旱区试水物联网灌溉技术,一年省出1.5个西湖

阿里巴巴正用物联网技术解决干旱地区的灌溉问题&#xff0c;通过搭建农业物联网平台&#xff0c;全面监测农作物的生长状态&#xff0c;从而匹配最节约的灌溉方案。12月19日试验区研究人员得出预测结果&#xff1a;一年可以省出1.5个西湖的水。 一直以来干旱是困扰人类的重要环…

网易考拉在服务化改造方面的实践

导读&#xff1a; 网易考拉&#xff08;以下简称考拉&#xff09;是网易旗下以跨境业务为主的综合型电商&#xff0c;自2015年1月9日上线公测后&#xff0c;业务保持了高速增长&#xff0c;这背后离不开其技术团队的支撑。微服务化是电商IT架构演化的必然趋势&#xff0c;网易…

Oracle 11g Java驱动包ojdbc6.jar安装到maven库,并查看jar具体版本号

ojdbc6.jar下载 Oracle官方宣布的Oracle数据库11g的驱动jar包是ojdbc6.jar ojdbc6.jar下载地址&#xff1a;https://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html (Oracle Database 11g Release 2 (11.2.0.4) JDBC Drivers & UCP Do…

阿里重磅开源Blink:为什么我们等了这么久?

12月20日&#xff0c;由阿里巴巴承办的 Flink Forward China 峰会在北京国家会议中心召开&#xff0c;来自阿里、华为、腾讯、美团点评、滴滴、字节跳动等公司的技术专家与参会者分享了各公司基于 Flink 的应用和实践经验。 感兴趣的开发者可以看云栖社区的对于大会的主会5场分…

GAN是一种特殊的损失函数?

数据科学家Jeremy Howard在fast.ai的《生成对抗网络&#xff08;GAN&#xff09;》课程中曾经讲过这样一句话&#xff1a; “从本质上来说&#xff0c;生成对抗网络&#xff08;GAN&#xff09;是一种特殊的损失函数。” 你是否能够理解这句话的意思&#xff1f;读完本文&…

matlab 三维 作图 坐标轴_这张图(不全),想利用matlab画一张三维图,X Y z 轴分别为经度 纬度 频率,这...

xrangeminx:dx:maxx; yrangeminy:dy:maxy;[X,Y] meshgrid(xrange,yrange);griddata(lon,lat,SST,X,Y);mesh(X,Y,Z), hold onplot3(lon,lat,SST,o),hold offmatlab 作图方法2113&#xff1a;plot3 三维曲线图&#xff1b;plot3(x1,y1,z1,x2,y2,z2,…,xn,yn,zn): surf(x,y,z)…

(Python)零起步数学+神经网络入门

在这篇文章中&#xff0c;我们将在Python中从头开始了解用于构建具有各种层神经网络&#xff08;完全连接&#xff0c;卷积等&#xff09;的小型库中的机器学习和代码。最终&#xff0c;我们将能够写出如下内容&#xff1a; 假设你对神经网络已经有一定的了解&#xff0c;这篇文…

短视频宝贝=慢?阿里巴巴工程师这样秒开短视频

前言 随着短视频兴起&#xff0c;各大APP中短视频随处可见&#xff0c;feeds流、详情页等等。怎样让用户有一个好的视频观看体验显得越来越重要了。大部分feeds里面滑动观看视频的时候&#xff0c;有明显的等待感&#xff0c;体验不是很好。针对这个问题我们展开了一波优化&am…

Haproxy 管控台介绍

Queue 队列 简称全称说明Curcurrent queued requests当前的队列请求数量Maxmax queued requests最大的队列请求数量Limit队列限制数量 Session rate (每秒的连接回话)列表 简称全称说明scurcurrent sessions每秒的当前回话的限制数量smaxmax sessions每秒的新的最大的回话量s…

阿里云时空数据库引擎HBase Ganos上线,场景、功能、优势全解析

随着全球卫星导航定位系统、传感网、移动互联网、IoT等技术的快速发展&#xff0c;越来越多的终端设备连接至网络&#xff0c;由此产生了大规模的时空位置信息&#xff0c;如车辆轨迹、个人轨迹、群体活动、可穿戴设备时空位置等。这些数据具有动态变化&#xff08;数据写入频繁…

云栖专辑|阿里开发者们的第二个感悟:PG大V德哥的使命感与开放心态

2015年12月20日&#xff0c;云栖社区上线。2018年12月20日&#xff0c;云栖社区3岁。 阿里巴巴常说“晴天修屋顶”。 在我们看来&#xff0c;寒冬中&#xff0c;最值得投资的是学习&#xff0c;是增厚的知识储备。 所以社区特别制作了这个专辑——分享给开发者们20个弥足珍贵的…

VS Code 全局配置

文章目录1. settings.json2. 在项目根目录添加.eslintrc.js3. 在项目根目录添加.prettierrc.json1. settings.json ctrlshirtp 搜索settings.json替换为下面内容即可 {// 主题颜色 浅色主题"workbench.colorTheme": "Monokai","workbench.iconTheme…

云栖专辑 | 阿里开发者们的第3个感悟:从身边开源开始学习,用过才能更好理解代码

2015年12月20日&#xff0c;云栖社区上线。2018年12月20日&#xff0c;云栖社区3岁。 阿里巴巴常说“晴天修屋顶”。 在我们看来&#xff0c;寒冬中&#xff0c;最值得投资的是学习&#xff0c;是增厚的知识储备。 所以社区特别制作了这个专辑——分享给开发者们20个弥足珍贵的…

个人帐目管理系统java_Java 项目 个人帐目管理系统

目录第一部分项目描述 31.1项目目的 3第二部分需求和开发环境 32.1使用技术和开发环境 32.2项目需求 32.3详细功能 32.4 E-R图 32.5数据库的设计 32.5.1数据表的设计 32.5.2数据库约束的设计 42.5.3数据库序列的设计 42.5.4数据库索引的设计 42.5.5数据库视图的设计 52.5.6数据…

KubeCon 2018 参会记录 —— FluentBit Deep Dive

在最近的上海和北美KubeCon大会上&#xff0c;来自于Treasure Data的Eduardo Silva&#xff08;Fluentd Maintainer&#xff09;带来了最期待的关于容器日志采集工具FluentBit的最新进展以及深入解析的分享&#xff1b;我们知道Fluentd是在2016年底正式加入CNCF&#xff0c;成为…

全球首个!阿里云开源批流一体机器学习平台Alink……

11月28日&#xff0c;阿里云正式开源机器学习平台 Alink&#xff0c;这也是全球首个批流一体的算法平台&#xff0c;旨在降低算法开发门槛&#xff0c;帮助开发者掌握机器学习的生命全周期。 Flink Forward 2019在京举办&#xff0c;吸引众多开发者参与标题Alink基于实时计算引…