This is a creation in Article, where the information may have evolved or changed.
Synchronization is suitable for multiple consecutive executions, each step of execution is dependent on the previous action, and asynchronous execution is independent of the Order of task execution (e.g. fetching data from 10 sites)
Synchronous Execution Class Runnerasync
Supports return time-out detection, system interrupt detection
Error constant definition
Timeout error var errtimeout = errors. New ("Received timeout")//Operating system interrupt error var Errinterrupt = errors. New ("Received interrupt")
The implementation code is as follows
Package Taskimport ("OS" "Time" "os/signal" "sync")//Asynchronous execution task type Runner struct {//operating system signal detection interrupt C Han os. Signal//Record execution status complete Chan error//timeout detection timeout <-chan time. Time//Save All tasks to be performed in order to perform tasks []func (id int) error waitgroup sync. Waitgroup lock Sync. Mutex errs []error}//new a Runner object func Newrunner (d time. Duration) *runner {return &runner{interrupt:make (Chan os). Signal, 1), Complete:make (chan error), Timeout:time. After (d), Waitgroup:sync. waitgroup{}, Lock:sync. mutex{},}}//adds a task func (this *runner) Add (Tasks ... func (id int) error) {this.tasks = append (This.tasks, Tasks ...) }//start Runner, monitor error message func (this *runner) Start () error {//Receive operating system signal signal. Notify (This.interrupt, OS. INTERRUPT)//Concurrent Execution Task go func () {This.complete <-this. Run ()} () select {//Return execution result case ERR: = <-this.complete:return Err//Timeout returns case <-this. TimEout:return Errtimeout}}//Asynchronously executes All tasks func (this *runner) the Run () error {for id, Task: = Range This.tasks { If This.gotinterrupt () {return errinterrupt} this.waitGroup.Add (1) go func (id int) { This.lock.Lock ()//Perform task ERR: = Task (ID)//locking save to result set This.errs = AP Pend (This.errs, Err) This.lock.Unlock () This.waitGroup.Done ()} (ID)} this.waitGroup.Wa It () return nil}//determines whether the operating system interrupt signal is received by Func (this *runner) Gotinterrupt () bool {Select {case <-this.interrupt: Stop receiving other signal signal. Stop (This.interrupt) return true//normal execution Default:return false}}//get execution finished Errorfunc (this *runner ) Geterrs () []error {return This.errs}
How to use
Add adds a task to receive a closure of type int
Start executes the wound, returns an error type, nil is executed, errtimeout represents the execution timeout, errinterrupt represents execution interrupted (like Ctrl + C operation)
Test the sample code
Package Taskimport ("Testing" "Time" "FMT" "OS" "Runtime") func Testrunnerasync_start (t *testing. T) {//Open multi-core runtime. Gomaxprocs (runtime. NUMCPU ())//Create runner object, set timeout Runner: = Newrunnerasync (8 * time). Second)//Add the running task Runner. ADD (Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), create Taskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (), Createtaskasync (),) fmt. PRINTLN ("Synchronous Execution of tasks")//start the execution of the task if err: = Runner. Start (); Err! = Nil {switch Err {case errtimeout:fmt. Println ("Execution timeout") OS. Exit (1) Case errinterrupt:fmt. Println ("task Interrupted") OS. Exit (2)}} t.Log ("Execution End")}//Create task to perform Func Createtaskasync () func (id int) {return func (id int) {FMT . Printf ("Performing%v tasks \ n", Id)//simulated task execution, sleep two seconds//time. Sleep (1 * time. Second)}}
Execution results
Synchronous execution task executing 0 tasks executing a task executing 2 tasks performing 3 tasks performing 4 tasks performing 5 tasks executing 6 tasks in progress the execution is 7 a task is executing 8 tasks performing 9 tasks executing 10 tasks executing 11 tasks performing a total of six task Runneras ync_test.go:49: End of execution
Asynchronous execution class runner
Supports return time-out detection, system interrupt detection
The implementation code is as follows
Package Taskimport ("OS" "Time" "os/signal" "sync")//Asynchronous execution task type Runner struct {//operating system signal detection interrupt C Han os. Signal//Record execution status complete Chan error//timeout detection timeout <-chan time. Time//Save All tasks to be performed in order to perform tasks []func (id int) error waitgroup sync. Waitgroup lock Sync. Mutex errs []error}//new a Runner object func Newrunner (d time. Duration) *runner {return &runner{interrupt:make (Chan os). Signal, 1), Complete:make (chan error), Timeout:time. After (d), Waitgroup:sync. waitgroup{}, Lock:sync. mutex{},}}//adds a task func (this *runner) Add (Tasks ... func (id int) error) {this.tasks = append (This.tasks, Tasks ...) }//start Runner, monitor error message func (this *runner) Start () error {//Receive operating system signal signal. Notify (This.interrupt, OS. INTERRUPT)//Concurrent Execution Task go func () {This.complete <-this. Run ()} () select {//Return execution result case ERR: = <-this.complete:return Err//Timeout returns case <-this. TimEout:return Errtimeout}}//Asynchronously executes All tasks func (this *runner) the Run () error {for id, Task: = Range This.tasks { If This.gotinterrupt () {return errinterrupt} this.waitGroup.Add (1) go func (id int) { This.lock.Lock ()//Perform task ERR: = Task (ID)//locking save to result set This.errs = AP Pend (This.errs, Err) This.lock.Unlock () This.waitGroup.Done ()} (ID)} this.waitGroup.Wa It () return nil}//determines whether the operating system interrupt signal is received by Func (this *runner) Gotinterrupt () bool {Select {case <-this.interrupt: Stop receiving other signal signal. Stop (This.interrupt) return true//normal execution Default:return false}}//get execution finished Errorfunc (this *runner ) Geterrs () []error {return This.errs}
How to use
Add a task to receive the int type, return a closure of type error
Start executes the wound, returns an error type, nil is executed, errtimeout represents the execution timeout, errinterrupt represents execution interrupted (like Ctrl + C operation)
Geterrs get all the task execution results
Test the sample code
Package Taskimport ("Testing" "Time" "FMT" "OS" "Runtime") func Testrunner_start (t *testing. T) {//Open multi-core runtime. Gomaxprocs (runtime. NUMCPU ())//Create runner object, set time-out Runner: = Newrunner (*. Second)//Add the running task Runner. ADD (CreateTask (), CreateTask (), CreateTask (), CreateTask (), CreateTask (), creat ETask (), CreateTask (), CreateTask (), CreateTask (), CreateTask (), CreateTask (), C Reatetask (), CreateTask (), CreateTask (),) fmt. PRINTLN ("Execute task Asynchronously")//Start executing task if err: = Runner. Start (); Err! = Nil {switch Err {case errtimeout:fmt. Println ("Execution timeout") OS. Exit (1) Case errinterrupt:fmt. Println ("task Interrupted") OS. Exit (2)}} t.Log ("Execution End") T.Log (runner. Geterrs ())}//creates the task to perform Func createtask () func (id int) Error {return func (id int) error {FMT. Printf ("Performing%v tasks \ n", id)//simulating task execution, Sleep//time. Sleep (1 * time. Second) return Nil}}
Execution results
An asynchronous execution task is performing 2 tasks executing a task executing 4 tasks performing 3 tasks performing 6 tasks executing 5 tasks executing 9 tasks doing 7 tasks executing 10 tasks executing 13 jobs executing 8 tasks executing 11 tasks Performing 12 task being performed 0 task being carried out by a total of five Service runner_test.go:49: Execution ends runner_test.go:51: [<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil>]