synchronize |?s??kr?na?z|A. transitive verb使同步 to synchronize [something] with [something]使某事物与某事物同步 B. intransitive verb«movement, sound, action» 同时发生 to synchronize with [something]与某事物同步
开启<创建>一条新的线程
//开启一条新的线程 这句话只是告诉CPU线程准备就绪,随时可以调度,并不是线程已经执行
调用thread 这个方法
[thread start];
谁来执行线程?
答:CPU来调度线程
线程什么时候来执行?
答:只有CPU知道
线程怎么执行代码?
答:按顺序执行其中的代码
当开启一条新的线程以后,就可以在执行耗时操作的同时,同时执行UI控件的点击事件,那是因为系统把耗时操作都放在了新开启的线程里面去执行
一个应用程序启动以后,会默认生成一条线程——主线程
自己创建的线程——子线程
问题
1>为什么开启一条新的线程之后,就会解决卡住主线程的问题?
答: (任务)并发执行 ===(任务)同时执行
2>为什么会把耗时操作放在子线程里面?
答:主线程所做的事情应该是响应用户输入,事件处理,更新UI,而耗时的任务不要在主线程中处理,由于耗时任务使的主线程被阻塞了.不能响应用户的请求,这样应用的用户体验会很差
3>在不同的线程中,任务是如何执行?
<(不管单核CPU还是双核CPU)每个CPU同一时间也是只能执行一个进程>
任务在CPU(进程是在CPU里面执行的)里面是快速切换的在执行,但是因为任务切换速度过快,就造成了任务同时执行的假象
4>一条线程是如何执行的?
答:同一条线程—任务是按顺序执行的(线程执行的是代码里面的代码块) 代码是从上到下,一个代码块一个代码块执行的
顺序执行——串行执行
5>多条线程(线程和线程之间)是如何执行的?
答:任务同时执行
同时执行---并发执行
主线程,又称为 UI线程 —处理UI操作(UI控件点击滚动等) --- 刷新数据也是在UI线程里面执行的
用户交互 --也要放在主线程里面来操作,而和用户进行交互的就是APP的UI
C语言创建线程
1>导入头文件
#import<pthread.h>
2>创建一条线程
mythread 是标示符的名字
2.1 线程标示符
pathread_t mythread;
/**
* <#pthread_t *restrict#>:线程标识符地址
<#const pthread_attr_t *restrict#>:设置线程的属性
<#void *(*)(void *)#>:执行任务、方法
C语言中:void * == OC id;
<#void *restrict#>:执行函数的参数
返回值:如果返回值为0 ,代表线程创建成功。
如果线程创建失败,返回错误的状态码
2.2 创建线程
int result = pthread_currate(&mythread,NULL,run,(__bridge void*)(str));
void *run(void *date)
{
for(int i = 0 ; i < 100; i++)
{
NSThread
currentThread 打印的是当前的线程
NSLog(@“%@,%@“,date, [NSThread currentThread ] );
}
//返回线程的属性
return NULL;
}
// 线程中执行的方法
/**
number = 1, name = main :主线程 number = 1 代表主线程。
* number = 2, name = (null) number != 1 代表非主线程、子线程
*
*/
// C Core Foundation
// OC Foundation
NSString *str4 = @"123456"; //OC对象
CFStringRef str2 = (__bridge CFStringRef)(str4); //把OC的对象传给C的对象 这个时候需要进行release
//对传过来的OC地址进行release
CFRelease(str2); //
当打印的线程不是1 的话,那么忙就是子线程只有1 是主线程
// 线程标识符
pthread_t mythread;
/**
* <#pthread_t *restrict#>:线程标识符地址
<#const pthread_attr_t *restrict#>:设置线程的属性
<#void *(*)(void *)#>:执行任务、方法
C语言中:void * == OC id;
<#void *restrict#>:执行函数的参数
返回值:如果返回值为0 ,代表线程创建成功。
NSLog(@“%d”,result); //打印的是0 表示线程创建成功
如果线程创建失败,返回错误的状态吗
*/
NSString *str = @"hello pthread";
//创建线程 需要用到这个参数
int result = pthread_create(&mythread, NULL, run, (__bridge void *)(str));
//打印一下看这条线程是否创建成功
NSLog(@"result = %d",result);
C语言中:void * == OC id;
如果线程创建失败,返回错误的状态吗
OC创建线程的第一种方法
1>可以设置的名字
2>可以设置线程的内存大小
3>可以设置线程的优先级
线程的优先级从0.0 到1.0 的值
值越小,代表线程的优先级越低
第二三种都是创建出来线程自动执行的 不用使用strat进行调用
线程的状态
线程创建好和线程准备就绪中间发生了什么事情?
答:放入可调度线程池
答:
可调度线程池:线程调度start这个方法
不可调度线程池: 线程刚被创建出来是在不可调度线程池里面的.是不可被调度的,等调用了start方法以后也只是告诉CPU线程准备就绪了,仍然未被调用
什么叫准备就绪:就是把创建出来的线程放到了可调度线程池里面,才叫线程准备就绪
线程的生命周期
线程刚被创造出来是在不可调度线程池里面,当前线程被调用start方法 的时候,线程会被放在可调度线程池里面,表示线程准备就绪,CPU随时可以调度,当CPU调度当前线程,线程运行完毕以后,线程死亡,死亡之前首先需要把执行完毕的线程从可调度线程池里面拿出来,这个时候线程的状态,就是死亡<销毁>
当线程在CPU里面的执行过程中(调度其他线程 )发生了卡顿,被卡在了某个点,这个时候线程的状态又会从运行状态变为,就绪状态,等待再次被调度
当一条线程在运行的过程当中,被赋予了sleep这个方法,那么当前的线程会被CPU从可调度线程池里面释放出来,释放出来的线程是睡眠状态,当想重新调度当前线程的时候,还需要把睡眠的线程重回新从不可调度线程池里面重新放到可调度线程池里面,这样线程才可以重新被调用
当线程运行的过程中程序意外崩溃,这样就需要人为的为线程添加一个exit(销毁)这个方法
当线程被强制退出以后,再点击控制器的view ,项目会强制退出
当多条线程按照顺序执行的时候,就需要线程同步技术
线程是由CPU来执行的,如果想让线程按照顺序来执行,就需要控制CPU
解决资源共享问题的方法
控制CPU的方法其实不能数是控制器CPU 只是在线程执行的时候,给当前线程加了一个锁,这样的话,每次就只能由一个线程在执行,然后按顺序执行
线程间通信
能用开启多线程做些什么?
答:做一些并发操作
子线程负责进行耗时操作
主线程负责显示图片
当子线程把图片下载好之后,主线程是怎么知道的这就涉及到了线程之间的通信
点击
下载
设置
把需要的数据定义为宏
计算出图片的宽高XY
创建一个图片框 把图片的宽高XY都传入这个图片框作为图片的框的frame
设置图片的框的颜色
把图片添加v控制器的view上
//
// ViewController.m
// 九宫格
//
// Created by renlei on .
// Copyright (c) 2015年 renlei. All rights reserved.
//
//定义九宫格的宏
/**
* 宽
* 高
* 间距
* 行数
* 列数
* 格子的数量
*/
//控制器宽
#define KWIDTH [UIScreen mainScreen].bounds.size.width
//控制器高
#define KDIGHT [UIScreen mainScreen].bounds.szie.height
//格子间的数量
#define KNUMBERS 100
//格子的间隙
#define KMARGIN 3
//格子的行数
#define KCOUNTS 5
//格子的列数
#define KROWS 5
//
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 图片的框
// 图片的宽
// KWIDTH 宽
// kMARGIN 间隙
// kCOUNTS 列数
// KROWS 行数
// 3 5 + 1 / 5
// (宽 - 间隙 * (列数 + 1)) / 列数 == 图片框的宽
CGFloat imageW = (KWIDTH - KMARGIN*(KCOUNTS + 1)) / KCOUNTS;
// 图片的高
// (宽 - 间隙 * (行数 + 1)) / 行数
CGFloat imaegH = (KWIDTH - KMARGIN * (KROWS + 1))/ KROWS;
//i < 格子的数量
for (int i = 0; i<KNUMBERS; i++) {
//格子所在的列
//格子的数量 模 格子的列数
int count = i%KCOUNTS;
//格子所在的行 //格子的数量 除以 格子的列数
int row = i / KCOUNTS;
//图片的X //格子的间隙 + (格子的间隙 + 图片的宽) * 列数
CGFloat imageX = KMARGIN + (KMARGIN + imageW) * count;
//图片的高 // 格子的间隙 + (格子的间隙 + 图片的高) * 行数
CGFloat imageY = KMARGIN + (KMARGIN + imaegH)*row;
//创建的图片
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(imageX, imageY, imageW, imaegH)];
//设置图片框颜色
imageView.backgroundColor = [UIColor greenColor];
//添加图片
[self.view addSubview:imageView];
}
}
@end