1.Synchronized和ReentratLock的区别
1)Lock是一个接口,synchronized是Java中的关键字,synchronized是内置的语言实现;
2)synchronized发生异常时,会自动释放线程占用的锁,故不会发生死锁现象。Lock发生异常,若没有主动释放,极有可能造成死锁,故需要在finally中调用unLock方法释放锁;
3)Lock可以让等待锁的线程响应中断,使用synchronized只会让等待的线程一直等待下去,不能响应中断
4)通过Lock可以知道有没有成功获取到锁,synchronized就不灵
5)Lock可以提高多个线程进行读操作的效率
2.Synchronized底层如何实现?锁升级过程
synchronized的代码块是什么:它是由一对儿monitorenter/monitorexit指令实现的,Monitor对象是同步的基本实现单元。不是很清楚锁升级过程
3.线程池有哪几种?分别什么特点
1、newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
这种类型的线程池特点是:
工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统OOM。
2、newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
3、newSingleThreadExecutor
创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO,
LIFO,
优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
4、newScheduleThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
5、newSingleThreadScheduledExecutor
创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行并且可定时或者延迟执行线程活动。
4.手写快速排序?多线程快速排序?
1)
public void quickSort(int[] a, int start, int end) {//start和end是要排序的区间
int i = start;
int j = end;//先把start和end保存下来,因为后面的递归会用到
if (start >= end) {//如果两个游标相遇,或者start>end,退出
return;
}
boolean flag = true;//定义一个标记,很重要
int temp;//定义临时变量,交换用
while (i != j) {//true是从左往右比,false是从右往左比
if (a[i] > a[j]) {//交换
temp = a[i];
a[i] = a[j];
a[j] = temp;
flag = !flag;//标志取反
}
if (flag) {如果是从左往右比
j--;
} else {如果是从右往左比
i++;
}
}
i--;
j++;//i,j都退一格
quickSort(a, start, i);//递归分号边的数组
quickSort(a, j, end);//递归分号边的数组
}```
2)
```java
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <sys/time.h>
#include <pthread.h>
#include <algorithm>
using namespace std;
const long MAX = 1e7L; // max num in array
const long long MAX_NUM = 1e8L; // num of element to sort
const int thread = 100;
const int thread_num = MAX_NUM / thread;
int num[MAX_NUM];
int tmp_num[MAX_NUM];
pthread_barrier_t barrier; // barrier
//Initialized Data
void init()
{
srand(1);
for (int i = 0; i < MAX_NUM; ++i) {
num[i] = rand() % MAX;
}
}
//Quick sort function
void qsorts(int* start, int* end) {
int nums = end - start;
if (nums > 0) {
int flag = start[0];
int i = 0;
int j = nums;
while (i < j) {
while (j > i && start[j] > flag) {
--j;
}
start[i] = start[j];
while (i < j && start[i] <= flag) {
++i;
}
start[j] = start[i];
}
start[i] = flag;
qsorts(start, start + i - 1);
qsorts(start + i + 1, end);
}
}
void* work(void* arg) {
long index = (long)arg;
qsorts(num+index, num+index+thread_num-1);
pthread_barrier_wait(&barrier);
pthread_exit(NULL);
}
void meger()
{
long index[thread];
for (int i = 0; i < thread; ++i)
{
index[i] = i * thread_num;
}
for(long i = 0; i < MAX_NUM; ++i)
{
long min_index;
long min_num = MAX;
for(int j = 0; j < thread; ++j)
{
if((index[j] < (j + 1) * thread_num)
&& (num[index[j]] < min_num))
{
min_index = j;
min_num = num[index[j]];
}
}
tmp_num[i] = num[index[min_index]];
index[min_index]++;
}
}
int main(int argc, char *argv[])
{
init();
struct timeval start, end;
pthread_t ptid;
printf("%ld %ld\n", num[1], num[2]);
gettimeofday(&start, NULL);
//init pthread and thread barrier
pthread_barrier_wait(&barrier);
//add 1, total have (thread+1) threads
for (int i = 0; i < thread; ++i) {
pthread_create(&ptid, NULL, work, (void*)(i*thread_num));
}
pthread_barrier_wait(&barrier);
meger();
gettimeofday(&end, NULL);
long long s_usec = start.tv_sec * 1000000 + start.tv_usec;
long long e_usec = end.tv_sec * 1000000 + end.tv_usec;
double useTime = (double)(e_usec - s_usec) / 1000000.0;
printf("sort use %.4f seconds\n", useTime);
return 0;
}