前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一些kubernetes的开发/实现/使用技巧-1

一些kubernetes的开发/实现/使用技巧-1

原创
作者头像
王磊-字节跳动
修改于 2019-12-11 11:40:43
修改于 2019-12-11 11:40:43
1.6K0
举报
文章被收录于专栏:01ZOO01ZOO

默认同步时间

代码语言:txt
AI代码解释
复制
--min-resync-period duration                                        The resync period in reflectors will be random between MinResyncPeriod and 2*MinResyncPeriod. (default 12h0m0s)

https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/apis/config/v1alpha1/defaults.go#L120 

判断 pod状态

代码语言:txt
AI代码解释
复制
// pkg/contoller/statefulset/stateful_set_utils.go
// isRunningAndReady returns true if pod is in the PodRunning Phase, if it has a condition of PodReady.
func isRunningAndReady(pod *v1.Pod) bool {
   return pod.Status.Phase == v1.PodRunning && podutil.IsPodReady(pod)
}

// isCreated returns true if pod has been created and is maintained by the API server
func isCreated(pod *v1.Pod) bool {
   return pod.Status.Phase != ""
}

// isFailed returns true if pod has a Phase of PodFailed
func isFailed(pod *v1.Pod) bool {
   return pod.Status.Phase == v1.PodFailed
}

// isTerminating returns true if pod's DeletionTimestamp has been set
func isTerminating(pod *v1.Pod) bool {
   return pod.DeletionTimestamp != nil
}

// isHealthy returns true if pod is running and ready and has not been terminated
func isHealthy(pod *v1.Pod) bool {
   return isRunningAndReady(pod) && !isTerminating(pod)
}


podutil 在pkg/api/v1/pod/util.go
// IsPodAvailable returns true if a pod is available; false otherwise.
// Precondition for an available pod is that it must be ready. On top
// of that, there are two cases when a pod can be considered available:
// 1. minReadySeconds == 0, or
// 2. LastTransitionTime (is set) + minReadySeconds < current time
func IsPodAvailable(pod *v1.Pod, minReadySeconds int32, now metav1.Time) bool {}

// IsPodReady returns true if a pod is ready; false otherwise.
func IsPodReady(pod *v1.Pod) bool {
	return IsPodReadyConditionTrue(pod.Status)
}

判断 job 状态

代码语言:txt
AI代码解释
复制
// pkg/controller/cronjob/utils.go
func getFinishedStatus(j *batchv1.Job) (bool, batchv1.JobConditionType) {
	for _, c := range j.Status.Conditions {
		if (c.Type == batchv1.JobComplete || c.Type == batchv1.JobFailed) && c.Status == v1.ConditionTrue {
			return true, c.Type
		}
	}
	return false, ""
}

// IsJobFinished returns whether or not a job has completed successfully or failed.
func IsJobFinished(j *batchv1.Job) bool {
	isFinished, _ := getFinishedStatus(j)
	return isFinished
}

判断 node 状态

代码语言:txt
AI代码解释
复制
// k8s.io/kubernetes/pkg/api/v1/node/util.go
func IsNodeReady(node *v1.Node) bool {
	for _, c := range node.Status.Conditions {
		if c.Type == v1.NodeReady {
			return c.Status == v1.ConditionTrue
		}
	}
	return false
}

kubelet 是如何找到 docker secrect的

代码语言:txt
AI代码解释
复制
// 1. if len(pod.Spec.ImagePullSecrets) == 0  注入 serviceaccount 的默认 secret
// plugin/pkg/admission/serviceaccount/admission.go
func (s *serviceAccount) Admit(a admission.Attributes) (err error)

// 2. 从 ImagePullSecrets 指向到 secret中 中提取 Secret
// pkg/kubelet/kubelet_pods.go
func (kl *Kubelet) getPullSecretsForPod(pod *v1.Pod) []v1.Secret 

// 3. pkg/credentialprovider/secrets/secrets.go
func MakeDockerKeyring(...){
    ...
    // secret 里面的 docker config 会提取到 basicKeyring 中
    return credentialprovider.UnionDockerKeyring{basicKeyring, defaultKeyring}
}


// 4. RegisterCredentialProvider 自动注入支持的 CredentialProvider
// 比如 .dockercfg 读文件, azure, aws
// pkg/credentialprovider/provider.go
func init() {
	RegisterCredentialProvider(".dockercfg",
		&CachingDockerConfigProvider{
			Provider: &defaultDockerConfigProvider{},
			Lifetime: 5 * time.Minute,
		})
}


// 5. 使用 keyring 找 auth 信息
// pkg/kubelet/kuberuntime/kuberuntime_image.go
keyring.Lookup(repoToPull)

// 6. 根据镜像地址找 LazyAuthConfiguration  BasicDockerKeyring Lookup
// LazyAuthConfiguration 里面有 provider 和 username,password (provider 注入)
// pkg/credentialprovider/keyring.go
func (dk *BasicDockerKeyring) Lookup(image string) ([]LazyAuthConfiguration, bool)


// 7. 使用 credentialprovider + LazyAuthConfiguration => Auth 信息
// pkg/kubelet/kuberuntime/kuberuntime_image.go
authConfig := credentialprovider.LazyProvide(currentCreds)

// 8. 使用 auth 拉镜像
// pkg/kubelet/kuberuntime/kuberuntime_image.go
m.imageService.PullImage(imgSpec, auth)

// 这里比较有意思的是 如果有多个 secret,那么会根据前缀判断是否匹配,对每个匹配的 secret都会用来
// 尝试 pull image。直到都失败
creds, withCredentials := keyring.Lookup(repoToPull)
if !withCredentials {
		imageRef, err := m.imageService.PullImage(imgSpec, nil, podSandboxConfig)
		//....
}
for _, currentCreds := range creds {
		imageRef, err := m.imageService.PullImage(imgSpec, auth, podSandboxConfig)
		// ...
}

给 plugin 注入信息

定义了一种 plugin interface,怎么支持给 plugin 设置必要的参数(各种 plugin 需要的参数可能不同)?

  • 可以定义一系列 wants interface, 即 set 函数,有 set 函数的,表示需要这种参数,给他设置
代码语言:txt
AI代码解释
复制
// pkg/kubeapiserver/admission/initializer.go

// WantsInternalKubeClientSet defines a function which sets ClientSet for admission plugins that need it
type WantsInternalKubeClientSet interface {
	SetInternalKubeClientSet(internalclientset.Interface)
	admission.InitializationValidator
}

// WantsInternalKubeInformerFactory defines a function which sets InformerFactory for admission plugins that need it
type WantsInternalKubeInformerFactory interface {
	SetInternalKubeInformerFactory(informers.SharedInformerFactory)
	admission.InitializationValidator
}

// WantsCloudConfig defines a function which sets CloudConfig for admission plugins that need it.
type WantsCloudConfig interface {
	SetCloudConfig([]byte)
}

// WantsRESTMapper defines a function which sets RESTMapper for admission plugins that need it.
type WantsRESTMapper interface {
	SetRESTMapper(meta.RESTMapper)
}

// WantsQuotaConfiguration defines a function which sets quota configuration for admission plugins that need it.
type WantsQuotaConfiguration interface {
	SetQuotaConfiguration(quota.Configuration)
	admission.InitializationValidator
}


// Initialize checks the initialization interfaces implemented by each plugin
// and provide the appropriate initialization data
func (i *PluginInitializer) Initialize(plugin admission.Interface) {
	if wants, ok := plugin.(WantsInternalKubeClientSet); ok {
		wants.SetInternalKubeClientSet(i.internalClient)
	}

	if wants, ok := plugin.(WantsInternalKubeInformerFactory); ok {
		wants.SetInternalKubeInformerFactory(i.informers)
	}

	if wants, ok := plugin.(WantsCloudConfig); ok {
		wants.SetCloudConfig(i.cloudConfig)
	}

	if wants, ok := plugin.(WantsRESTMapper); ok {
		wants.SetRESTMapper(i.restMapper)
	}

	if wants, ok := plugin.(WantsQuotaConfiguration); ok {
		wants.SetQuotaConfiguration(i.quotaConfiguration)
	}
}

cronjob contoller 效率很低

还在使用定期 relist 方法的 contoller, 很多 job 会使 apiserver 压力很大

代码语言:txt
AI代码解释
复制
// pkg/controller/cronjob/cronjob_controller.go

go wait.Until(jm.syncAll, 10*time.Second, stopCh)

func (jm *CronJobController) syncAll() {
	// ...
	jl, err := jm.kubeClient.BatchV1().Jobs(metav1.NamespaceAll).List(metav1.ListOptions{})
	// ...
	
// 里面有大量使用 KubeClient 去apiserver 拿数据,而一般的 contoller 实现
// 获取数据会尽可能的使用 Lister 等去获取数据,本质是从 Indexer (cache) 中获取

vistor 模式

vistor 模式 在 kubernetes 里面很常用, 给外部函数 遍历内部状态的入口, 下面是几个例子

代码语言:txt
AI代码解释
复制
// 例子1: each
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go
func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error {
	field, ok := obj.Object["items"]
	if !ok {
		return errors.New("content is not a list")
	}
	// ... 略
	for _, item := range items {
		child, ok := item.(map[string]interface{})
		// ... 略
		if err := fn(&Unstructured{Object: child}); err != nil {
		    // 调用外部函数,外部函数如果 err,则 break each 流程
			return err
		}
	}
	return nil
}

// 例子2: visitor
// pkg/api/pod/util.go 允许外部访问 Pod 内部的所有引用的 configMapName
func VisitPodConfigmapNames(pod *api.Pod, visitor Visitor) bool {
	VisitContainers(&pod.Spec, func(c *api.Container) bool {
		return visitContainerConfigmapNames(c, visitor)
	})
	var source *api.VolumeSource
	for i := range pod.Spec.Volumes {
		source = &pod.Spec.Volumes[i].VolumeSource
		switch {
		case source.Projected != nil:
			// .. 略
			if !visitor(source.Projected.Sources[j].ConfigMap.Name) {}
			//.. 略
		case source.ConfigMap != nil:
			if !visitor(source.ConfigMap.Name) {}
		}
	}
	return true
}

context 使用

kubernetes 里面 context 用得很多,在定义 interface 给 plugin, 或者其他地方实现的时候第一个参数经常是 context.

代码语言:txt
AI代码解释
复制
// 一个关联知识点 
// 1. 对 nil channel中读写数据会一直被block。
// 2. close的channel 读立即返回零值,写会panic,无论读写都不会阻塞。

// 使用说明: https://blog.golang.org/context
// Incoming requests to a server should create a Context, and outgoing
// calls to servers should accept a Context. The chain of function
// calls between them must propagate the Context, optionally replacing
// it with a derived Context created using WithCancel, WithDeadline,
// WithTimeout, or WithValue. When a Context is canceled, all
// Contexts derived from it are also canceled.


// A Context carries a deadline, cancelation signal, and request-scoped values
// across API boundaries. Its methods are safe for simultaneous use by multiple
// goroutines.
type Context interface {
    // Done returns a channel that is closed when this Context is canceled
    // or times out.
    Done() <-chan struct{}

    // Err indicates why this context was canceled, after the Done channel
    // is closed.
    Err() error

    // Deadline returns the time when this Context will be canceled, if any.
    Deadline() (deadline time.Time, ok bool)

    // Value returns the value associated with key or nil if none.
    Value(key interface{}) interface{}
}


// 常用的使用模式 break if cancel 
func Stream(ctx context.Context, out chan<- Value) error {
    for {
		v, err := DoSomething(ctx)
  		if err != nil { return err }
  		select {
  		case <-ctx.Done():
  			return ctx.Err()
  		case out <- v:
  		}
  	}
}

// 简化的 google search 例子
func handleSearch(w http.ResponseWriter, req *http.Request) {
    timeout, err := time.ParseDuration(req.FormValue("timeout"))
	if err == nil {
		ctx, cancel = context.WithTimeout(context.Background(), timeout)
	} else {
		ctx, cancel = context.WithCancel(context.Background())
	}
	defer cancel() // Cancel ctx as soon as handleSearch returns.
	
	results, err := search(ctx, query)
	// ...略
}

// Search sends query to Google search and returns the results.
func Search(ctx context.Context, query string) (Results, error) {
	// ...略
	err = httpDo(ctx, req, func(resp *http.Response, err error) error {
		// 略
		results = xxx
		return nil
	})
	// httpDo waits for the closure we provided to return, so it's safe to read results here.
	return results, err
}

// httpDo issues the HTTP request and calls f with the response. If ctx.Done is
// closed while the request or f is running, httpDo cancels the request, waits
// for f to exit, and returns ctx.Err. Otherwise, httpDo returns f's error.
func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
	// Run the HTTP request in a goroutine and pass the response to f.
	c := make(chan error, 1)
	req = req.WithContext(ctx)
	go func() { c <- f(http.DefaultClient.Do(req)) }()
	select {
	case <-ctx.Done():// 被取消了 (可能是 timeout 触发的)
		<-c // Wait for f to return.
		return ctx.Err()
	case err := <-c:
		return err
	}
}

// 另一个例子 这是一个收到一个信息 stop 两个信号退出的函数
func SetupSignalHandler(parent context.Context) context.Context {
	close(onlyOneSignalHandler) // panics when called twice
	ctx, cancel := context.WithCancel(parent)

	c := make(chan os.Signal, 2)
	signal.Notify(c, shutdownSignals...)
	go func() {
		<-c
		cancel() // 收到信号,取消 ctx, 后面使用这个 ctx 的任务都会 done
		<-c
		os.Exit(1) // second signal. Exit directly.
	}()

	return ctx
}


// 另一个例子 来自kubernetes scheduler
func Run(c schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error {
	// ...略
	// Prepare a reusable run function.
	run := func(ctx context.Context) {
		sched.Run()
		<-ctx.Done()
	}

	ctx, cancel := context.WithCancel(context.TODO()) // TODO once Run() accepts a context, it should be used here
	defer cancel()

	go func() {
		select {
		case <-stopCh:
			cancel()
		case <-ctx.Done():
		}
	}()

	// If leader election is enabled, run via LeaderElector until done and exit.
	if c.LeaderElection != nil {
		// ...略
		leaderElector.Run(ctx)
		return fmt.Errorf("lost lease")
	}

	// Leader election is disabled, so run inline until done.
	run(ctx)
	return fmt.Errorf("finished without leader elect")
}


// 再来最后一个例子,如何实现这样一个函数, retry f,直到 f 成功或者 timeout
// 对于这个例子 更通用的实现见 k8s.io/apimachinery/pkg/util/wait/wait.go 
// 不过 wait 中的 timeout 并不准确, 它在 重复的时候才会检查 timeout 
func Retry(fn func(ctx context.Context) error, timeout time.Duration) error {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	c := make(chan error, 1)
	for {
		go func() { c <- fn(ctx) }()
		select {
		case <-ctx.Done():
			return ctx.Err() // timeout error
		case err := <-c:
			if err == nil {
				return nil
			}
		}
	}
}

如何让一个 pod 运行到一个 node 上

由于 node 可能有 taint,需要 设置 Toleration, 可以参考 deamonsetcontroller 加了哪些

代码语言:txt
AI代码解释
复制
// pkg/controller/daemon/util/daemonset_util.go
func AddOrUpdateDaemonPodTolerations(spec *v1.PodSpec) {
    TaintNodeNotReady
    TaintNodeUnreachable
    TaintNodeDiskPressure
    TaintNodeMemoryPressure
    TaintNodePIDPressure
    TaintNodeUnschedulable
    TaintNodeNetworkUnavailable
}

获取某个资源的 controller

代码语言:txt
AI代码解释
复制
// staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/controller_ref.go
func IsControlledBy(obj Object, owner Object) bool
func GetControllerOf(controllee Object) *OwnerReference
func NewControllerRef(owner Object, gvk schema.GroupVersionKind) *OwnerReference

List 相关的工具

代码语言:txt
AI代码解释
复制
// staging/src/k8s.io/apimachinery/pkg/api/meta/help.go
func IsListType(obj runtime.Object) bool
func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error 
func ExtractList(obj runtime.Object) ([]runtime.Object, error) 
func SetList(list runtime.Object, objects []runtime.Object) error

Accessor

Accessor 是用来获取\设置 kubernetes api object 中的部分信息的工具

代码语言:txt
AI代码解释
复制
// staging/src/k8s.io/apimachinery/pkg/api/meta/meta.go
func CommonAccessor(obj interface{}) (metav1.Common, error)
func ListAccessor(obj interface{}) (List, error)
func Accessor(obj interface{}) (metav1.Object, error)
func TypeAccessor(obj interface{}) (Type, error)
func (resourceAccessor) SetKind(obj runtime.Object, kind string) error //....
func (a genericAccessor) SetNamespace(namespace string) //....

collisionCount 是什么

很多 kubernetes 资源都有一个 collisionCount 字段,主要是为了预防 hash 冲突,不同的 spec template 一般会计算出一个 hash, 作为 name 的一部分,比如 deployment 使用这个作为生成的 replica 的 name 的一部分 (1.12 之前不会直接加,会encode一下,1.12之后就是直接加的了) (也会加到 label/selector 里面 key 为 pod-template-hash), 如果只用 spec template,那么就有可能 name 冲突,使用 collisionCount 就能避免这种冲突的出现.

garbagecollector 是怎么实现的

代码语言:txt
复制

如何删除所有/一种资源

代码语言:txt
AI代码解释
复制
// get all deletable resources
resources, err := namespaceKubeClient.Discovery().ServerPreferredNamespacedResources()
deletableResources := discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"delete"}}, resources)
groupVersionResources, err := discovery.GroupVersionResources(deletableResources)
// each gvr and delete collection
for gvr := range groupVersionResources {
    metadataClient.Resource(gvr).Namespace(namespace).DeleteCollection(opts, metav1.ListOptions{})
}

pod hpa 是怎么工作的

代码语言:txt
复制

基本计算公式

代码语言:txt
AI代码解释
复制
# 比如 AverageValue 的情况
utilization=0
for _, val := range metrics {
	utilization = utilization + val
}

replicaCount = statusReplicas
usageRatio := float64(utilization) / (float64(targetUtilizationPerPod) * float64(replicaCount))
if math.Abs(1.0-usageRatio) > c.tolerance {
	// update number of replicas if the change is large enough
	replicaCount = int32(math.Ceil(float64(utilization) / float64(targetUtilizationPerPod)))
}

GVK 转成 GR

代码语言:txt
AI代码解释
复制
GV + Kind -> GK -> RESTMapping() -> GR

schema.ParseGroupVersion   
apimeta.RESTMapper.RESTMappings 
mapping.Resource.GroupResource()

type RESTMapping struct {
	// Resource is the GroupVersionResource (location) for this endpoint
	Resource schema.GroupVersionResource
	// GroupVersionKind is the GroupVersionKind (data format) to submit to this endpoint
	GroupVersionKind schema.GroupVersionKind
	// Scope contains the information needed to deal with REST Resources that are in a resource hierarchy
	Scope RESTScope
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
【原创】Java并发编程系列25 | 交换器Exchanger
很尴尬,发了并发编程的26和27,漏了本篇25。这下子我是真的没存货了哈哈。那下面我们来补上25先,25比较短小...勿喷。
java进阶架构师
2020/07/03
3200
玩转JUC工具,Java并发编程不再危机四伏
当今互联网应用普遍需要支持高并发访问,而Java作为一种广泛使用的编程语言,其并发编程能力对于实现高性能的应用非常重要。而Java的JUC(java.util.concurrent)并发工具就提供了许多实用的工具类和接口,可以让Java应用轻松实现高效的并发编程。
科技新语
2023/04/04
3900
Java并发编程--Exchanger
  用于线程间数据的交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange()方法,它会一直等待第二个线程也执行exchange方法,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。
在周末
2019/08/26
4360
理解Java并发工具类Exchanger
Exchanger类是JDK5中的一个并发工具辅助类,这个类的主要作用是可以用于两个线程之间交换数据,以实际生活中的场景来讲,比如很多小区楼下都有自取的快递柜,如果快递员来了,就把东西直接放快递柜子就行了,然后我们直接从柜子中取走东西即可。这个柜子就起到了媒介的作用。也就说柜子可以是双向信息交换的一个媒介,比如我需要邮寄东西,我可以提前把东西放进柜子,然后快递来了把新买的东西放进去,然后把需要邮寄的东西拿走,这样就完成了交换,但大多数时候,我们可能买东西比较多,邮寄东西比较少。 Exchanger在遗传算法和管道设计比较有用。
我是攻城师
2018/09/30
1.2K0
理解Java并发工具类Exchanger
Juc并发编程16——Semaphore,Exchanger,Fork/Join框架
java中的信号量也有很大的作用,它可以限制一个代码块可以同时被访问的线程数量(加排他锁锁可以限制只被一个线程访问),相当于流量控制。简单来说,它就是一个可以被N个线程同时占用的排它锁(因此也支持公平锁和非公平锁)。在初始时,可以指定Semaphore的许可证个数,一个线程可以获取一个或者多个许可证,当许可证不足以供其它线程获取时,想要竞争同步资源的其它线程将会被阻塞。
半旧518
2022/10/26
1870
Juc并发编程16——Semaphore,Exchanger,Fork/Join框架
面了个 5 年 Java,两个线程进行数据交换都不会,我真是醉了。。
点击关注公众号,Java干货及时送达 大家好,我是栈长。 面试总结 最近栈长面试了一个 5 年经验的 Java 程序员,简历和个人介绍都提到了精通 Java 多线程,于是我就问了几个多线程方面的问题: 1、实现多线程有哪几种方式,如何返回结果? 2、多个线程如何实现顺序访问? 3、两个线程如何进行数据交换? 4、如何统计 5 个线程的运行总耗时? 5、如何将一个任务拆分成多个子任务执行,最后合并结果? 大概问了他这几个问题,答的并不是太好,3、4、5 题都没有真正答上来,其实这几个问题在 JDK 包中都有
Java技术栈
2022/06/13
4510
面了个 5 年 Java,两个线程进行数据交换都不会,我真是醉了。。
【死磕Java并发】—–J.U.C之并发工具类:Exchanger
前面三篇博客分别介绍了CyclicBarrier、CountDownLatch、Semaphore,现在介绍并发工具类中的最后一个Exchange。Exchange是最简单的也是最复杂的,简单在于API非常简单,就一个构造方法和两个exchange()方法,最复杂在于它的实现是最复杂的(反正我是看晕了的)。 在API是这么介绍的:可以在对中对元素进行配对和交换的线程的同步点。每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象。Exchanger 可能被
用户1655470
2018/04/26
8380
Java并发编程之CyclicBarrier
CyclicBarrier字面意思是循环屏障,它可以实现线程间的计数等待。当线程到达屏障点时会依次进入等待状态,直到最后一个线程进入屏障点时会唤醒等待的线程继续运行。
布禾
2021/04/09
4210
Java并发编程之Semaphore
Semaphore是用来限制访问特定资源的并发线程的数量,相对于内置锁synchronized和重入锁ReentrantLock的互斥性来说,Semaphore可以允许多个线程同时访问共享资源。
布禾
2021/04/15
2200
Java Concurrent Exchanger
Exchanger是JUC里提供的供两个线程之间交换数据或者交互的一个并发工具,API也非常简单就两个重载的exchange泛型方法。
邹志全
2019/07/31
3400
Java并发-28.并发工具类-Exchanger
Exchanger用于进行线程间的数据交换。 提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。 第一个线程执行exchange方法,阻塞等待第二个线程也执行exchange方法,都到达同步点时,线程就可以交换数据 exchange(V x, long timeout, TimeUnit unit)方法可以超时等待 import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import ja
悠扬前奏
2019/06/13
3880
AQS-Exchanger源码学习
上文:AQS-semaphore&CyclicBarrier&CountDownLatch源码学习
逍遥壮士
2023/02/28
2020
AQS-Exchanger源码学习
并发编程之Exchanger
一、简介 Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。 注:Exchanger可以在两个线程之间交换数据,只能是2个线程,他不支持更多的线程之间互换数据。 二、Exchang
lyb-geek
2018/03/27
6860
Java的并发工具类汇总
如果需要原子更新引用类型变量的话,为了保证线程安全,atomic也提供了相关的类:
用户3467126
2019/08/09
4640
java并发编程(五)
阻塞队列:在某些情况下,会挂起线程,一旦条件满足,被挂起的线程会自动唤醒。而阻塞队列无需关心什么时候阻塞,什么时候唤醒。
疯狂的KK
2020/03/25
3050
Java并发编程之CountDownLatch
CountDownLatch(闭锁)是一个很有用的工具类,利用它我们可以拦截一个或多个线程使其在某个条件成熟后再执行。
xiangzhihong
2022/11/30
2320
【死磕Java并发】常用并发工具类详解
在前几篇文章中,我们讲到了线程、线程池、BlockingQueue 等核心组件,其实 JDK 给开发者还提供了比synchronized更加高级的线程同步组件,比如 CountDownLatch、CyclicBarrier、Semaphore、Exchanger 等并发工具类。
Java极客技术
2023/12/13
7280
【死磕Java并发】常用并发工具类详解
深入剖析Java并发库:Exchanger的工作原理与应用场景
码到三十五 : 个人主页 心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 !
公众号:码到三十五
2024/03/24
1620
深入剖析Java并发库:Exchanger的工作原理与应用场景
Java并发工具那些事儿
Java并发工具类主要有CyclicBarrier、CountDownLatch、Semaphore和Exchanger,日常开发中经常使用的是CountDownLatch和Semaphore。下面就简单分析下这几个并发工具类:
luoxn28
2020/03/11
4380
Java并发编程系列-(2) 线程的并发工具类
JDK 7中引入了fork-join框架,专门来解决计算密集型的任务。可以将一个大任务,拆分成若干个小任务,如下图所示:
码老思
2023/10/19
2450
Java并发编程系列-(2) 线程的并发工具类
相关推荐
【原创】Java并发编程系列25 | 交换器Exchanger
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 默认同步时间
  • 判断 pod状态
  • 判断 job 状态
  • 判断 node 状态
  • kubelet 是如何找到 docker secrect的
  • 给 plugin 注入信息
  • cronjob contoller 效率很低
  • vistor 模式
  • context 使用
  • 如何让一个 pod 运行到一个 node 上
  • 获取某个资源的 controller
  • List 相关的工具
  • Accessor
  • collisionCount 是什么
  • garbagecollector 是怎么实现的
  • 如何删除所有/一种资源
  • pod hpa 是怎么工作的
  • GVK 转成 GR
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档