Go基础(协程)--11.19

以下内容大部分引入:Go语言101,可自行观看。(微信公众号好像打不开超链接)

协程

Go不支持创建系统线程,所以协程是一个Go程序内部唯一的并发实现方式。

协程有时也被称为绿色线程。绿色线程是由程序的运行时(runtime)维护的线程。一个绿色线程的内存开销和情景转换(context switching)时耗比一个系统线程常常小得多。 只要内存充足,一个程序可以轻松支持上万个并发协程。

每个Go程序启动的时候只有一个对用户可见的协程,我们称之为主协程。 一个协程可以开启更多其它新的协程。在Go中,开启一个新的协程是非常简单的。 我们只需在一个函数调用之前使用一个go关键字,即可让此函数调用运行在一个新的协程之中。

并发同步

如果程序执行时没有同步会非常容易出现幻读,脏写等问题。这里直接引用书中的例子:

package main

import (
	"log"
	"math/rand"
	"time"
	"sync"
)

var wg sync.WaitGroup

func SayGreetings(greeting string, times int) {
	for i := 0; i < times; i++ {
		log.Println(greeting)
		d := time.Second * time.Duration(rand.Intn(5)) / 2
		time.Sleep(d)
	}
	wg.Done() // 通知当前任务已经完成。
}

func main() {
	rand.Seed(time.Now().UnixNano()) // Go 1.20之前需要
	log.SetFlags(0)
	wg.Add(2) // 注册两个新任务。
	go SayGreetings("hi!", 10)
	go SayGreetings("hello!", 10)
	wg.Wait() // 阻塞在这里,直到所有任务都已完成。
}

一个协程创建成功后会自动进入运行状态,协程只能用运行状态退出,不能从阻塞状态退出。如果协程一直在阻塞状态一般称之为死锁,当程序死锁后会报错。

延迟函数调用

在Go中,一个函数调用可以跟在一个defer关键字后面,成为一个延迟函数调用。 此defer关键字和此延迟函数调用一起形成一个延迟调用语句。当一个延迟调用语句被执行时,其中的延迟函数调用不会立即被执行,而是被推入由当前协程维护的一个延迟调用队列(一个后进先出队列)。类似Java中的压栈弹栈。

func main() {
	defer fmt.Println("9")
	fmt.Println("0")
	defer fmt.Println("8")
	fmt.Println("1")
	if false {
		defer fmt.Println("not reachable")
	}
	defer func() {
		defer fmt.Println("7")
		fmt.Println("3")
		defer func() {
			fmt.Println("5")
			fmt.Println("6")
		}()
		fmt.Println("4")
	}()
	fmt.Println("2")
	return
}

输出结果为:

另外一个例子:

因为这个延迟函数会在return之后执行,而return并不会直接返回,return本质上就是赋值,他等价于:r = n + n;return r;所以 r 就等于 10,r += n;再返回就会返回15

package main

import "fmt"

func Triple(n int) (r int) {
	defer func() {
		r += n // 修改返回值
	}()

	return n + n // <=> r = n + n; return
}

func main() {
	fmt.Println(Triple(5)) // 15
}

细节:入栈的时候会把值压入栈,也就是说压栈的时候当时的值是 1 出栈的值也是1。

协程和延迟调用的实参的估值时刻

直接看图:

最终结果为:

这块没弄太懂,个人理解为:第一个函数执行的时候进栈记录的是i的值,所以会输出 2 1 0。第二个函数是函数结束后执行的延迟函数,当时i的值是3,所以执行结果是 3 3 3。

这个代码太妙了!!协程开启的时候 a 的值为 123,x == a,后来程序继续往下走,把 a 重新赋值为 789 ,程序睡眠两秒保证同步,最终结果为123 789。太妙了!!!

今天到这!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,根据您的需求,我为您编写了如下代码。 首先,我们需要加载所需的包和数据: ```R library(xlsx) library(randomForest) library(keras) library(e1071) data_path <- "D:/Desktop/002362hwkj.xlsx" stk_data <- read.xlsx(data_path, sheetIndex = 1) ``` 然后,我们将数据按时间升序排列,并将日期列转化为日期格式: ```R stk_data$Date <- as.Date(stk_data$Date) stk_data <- stk_data[order(stk_data$Date),] ``` 接下来,我们将数据划分为训练集和测试集。由于您没有指定测试集的时间范围,这里我将最后一年的数据作为测试集: ```R train_data <- stk_data[1:(nrow(stk_data)-252),] test_data <- stk_data[(nrow(stk_data)-251):nrow(stk_data),] ``` 然后,我们为每个模型准备数据。对于随机森林和支持向量机,我们只需要选择需要的特征并将其转化为矩阵格式。对于长短期记忆神经网络,我们需要将数据转化为时间序列格式,并将其标准化。 ```R # 随机森林和支持向量机 train_rf_svm <- train_data[,c("Open", "Close", "Volume")] train_rf_svm <- data.matrix(train_rf_svm) test_rf_svm <- test_data[,c("Open", "Close", "Volume")] test_rf_svm <- data.matrix(test_rf_svm) # 长短期记忆神经网络 train_lstm <- train_data[,c("Close")] train_lstm <- data.matrix(train_lstm) scaler <- preProcess(train_lstm, method = c("scale", "center")) train_lstm <- predict(scaler, train_lstm) test_lstm <- test_data[,c("Close")] test_lstm <- data.matrix(test_lstm) test_lstm <- predict(scaler, test_lstm) train_lstm <- array(train_lstm, dim = c(nrow(train_lstm), 1, 1)) test_lstm <- array(test_lstm, dim = c(nrow(test_lstm), 1, 1)) ``` 接下来,我们分别训练随机森林、长短期记忆神经网络和支持向量机,并对测试集进行预测: ```R # 随机森林 rf_model <- randomForest(train_rf_svm[,1:2], train_rf_svm[,3], ntree = 500) rf_pred <- predict(rf_model, test_rf_svm[,1:2]) # 长短期记忆神经网络 lstm_model <- keras::keras_model_sequential() lstm_model %>% layer_lstm(units = 50, input_shape = c(1, 1)) %>% layer_dense(units = 1) lstm_model %>% compile(loss = 'mean_squared_error', optimizer = 'adam') lstm_model %>% fit(train_lstm[,1:1,], train_lstm[,1,], epochs = 100, batch_size = 32) lstm_pred <- predict(lstm_model, test_lstm)[,1] # 支持向量机 svm_model <- svm(train_rf_svm[,1:2], train_rf_svm[,3], kernel = "linear") svm_pred <- predict(svm_model, test_rf_svm[,1:2]) ``` 最后,我们计算三个模型的准确率,并绘制时间序列图: ```R # 计算准确率 rf_accuracy <- sum(rf_pred == test_rf_svm[,3])/nrow(test_rf_svm) lstm_accuracy <- sum(round(lstm_pred) == test_lstm[,1])/nrow(test_lstm) svm_accuracy <- sum(svm_pred == test_rf_svm[,3])/nrow(test_rf_svm) cat("随机森林准确率:", rf_accuracy, "\n") cat("LSTM准确率:", lstm_accuracy, "\n") cat("支持向量机准确率:", svm_accuracy, "\n") # 绘制时间序列图 par(mfrow=c(3,1)) plot(test_data$Date, test_data$Close, type = "l", col = "blue", xlab = "", ylab = "Price") lines(test_data$Date, rf_pred, col = "red") legend("bottomright", legend = c("Actual", "Predicted"), col = c("blue", "red"), lty = c(1, 1)) plot(test_data$Date, test_data$Close, type = "l", col = "blue", xlab = "", ylab = "Price") lines(test_data$Date, round(lstm_pred), col = "red") legend("bottomright", legend = c("Actual", "Predicted"), col = c("blue", "red"), lty = c(1, 1)) plot(test_data$Date, test_data$Close, type = "l", col = "blue", xlab = "", ylab = "Price") lines(test_data$Date, svm_pred, col = "red") legend("bottomright", legend = c("Actual", "Predicted"), col = c("blue", "red"), lty = c(1, 1)) ``` 注意:由于数据未提供证券代码,代码中的模型训练和预测均基于数据的 Close 列。如果您的数据中包含多个证券的交易数据,请修改代码以适配您的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ming__GoGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值