-
2020-12-11 09:09:33
python多线程练习题
多线程练习题目,涉及知识点较多,属于很好的练习题。
题目要求
通过多线程实现类似linux中的>>功能,也就是将日志记录到指定的文件中。
题目分析
基本为main.py写主要处理逻辑,utils.py构造工具类及对应的方法。
main.py
定义Server()类,类中定义方法输出内容。
实例化工具类,启动线程,设置标准输出和错误输出至日志文件。
实例化Server()类并调用方法进行内容的持续输出。
utils.py
定义工具类,工具类需要传入参数:日志名称。
首先判断日志是否存在,若不存在则创建,然后写入日志;存在则追加写入日志。
实现
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sys
from queue1.log_out.utils import TraceLog
class Server(object):
def log(self):
print("start server")
for i in range(100):
print(i)
print("end server") #print的实现是调用sys.stdout.write()方法
if __name__ == "__main__":
traceLog = TraceLog("main.log")
traceLog.start()
sys.stdout = traceLog
sys.stderr = traceLog
server = Server()
server.log() #print将会调用traceLog.write()方法
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import codecs
from threading import Thread, Lock
import os
class TraceLog(Thread):
def __init__(self, logName):
super(TraceLog, self).__init__() #调用父类的初始化方法
self.logName = logName
self.lock = Lock()
self.contexts = []
self.isFile()
def isFile(self):
if not os.path.exists(self.logName):
with codecs.open(self.logName, 'w') as f:
f.write("this log name is :{0}\n".format(self.logName))
f.write("start log\n")
def write(self, context):
self.contexts.append(context) #将需要输出的内容追加至列表中
def run(self):
while 1:
self.lock.acquire()
if len(self.contexts) != 0:
with codecs.open(self.logName, 'a') as f: #追加方式写入文件
for context in self.contexts:
f.write(context)
del self.contexts[:] #每次写入完成后清空列表
self.lock.release()
输出结果
当前目录下会生成main.log文件,文件内容如下
1
2
3
4
5
6
7
8
9
10
11
this log name is :main.log
start log
start server
0
1
2
.
.
98
99
end server
涉及文件读写、锁、多线程、sys模块、os模块等内容。
更多相关内容 -
多线程demo/java多线程练习
2019-05-17 14:28:59手写多线程demo,模拟数据库练习。感谢技术分享感谢技术分享感谢技术分享..感谢技术分享感谢技术分享感谢技术分享.. -
多线程练习程序 之 模拟火车票售票系统01版-附件资源
2021-03-02 15:10:23多线程练习程序 之 模拟火车票售票系统01版-附件资源 -
java多线程之赛马程序实验8多线程练习下载进度
2020-05-19 13:56:48运用多线程技术,练习Thread类得run方法和start方法。运用进度条显式表示下载进度。java多线程之赛马程序 -
Java多线程练习
2021-04-26 14:16:59Java多线程练习 在main方法中使用三个线程,向一个List集合中按顺序添加1到10共十个数字,添加完成后在控制台打印这个List的值(应该是[1,2,3,4,5,6,7,8,9,10]),然后结束程序执行。 import java.util.ArrayList; ...Java多线程练习
在main方法中使用三个线程,向一个List集合中按顺序添加1到10共十个数字,添加完成后在控制台打印这个List的值(应该是[1,2,3,4,5,6,7,8,9,10]),然后结束程序执行。
import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ThreadTest { private int flag = 1; private int count = 1; private final Lock lock = new ReentrantLock(); private final Condition conditionA = lock.newCondition(); private final Condition conditionB = lock.newCondition(); private final Condition conditionC = lock.newCondition(); volatile List<Integer> list = new ArrayList<>(); public void addA() { if (count >= 9) return; lock.lock(); try { if (flag != 1) { conditionA.await(); } list.add(count); count++; flag = 2; // 唤醒B conditionB.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void addB() { if (count >= 9) return; lock.lock(); try { if (flag != 2) { conditionB.await(); } list.add(count); count++; flag = 3; // 唤醒C conditionC.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public void addC() { if (count >= 9) return; lock.lock(); try { if (flag != 3) { conditionC.await(); } list.add(count); count++; flag = 1; // 唤醒A conditionA.signal(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } public List<Integer> getList() { return list; } }
public class Test3 { static Thread t1 ,t2,t3; public static void main(String[] args) { List<Thread> threadList = new ArrayList<>(); ThreadTest threadTest = new ThreadTest(); t1 = new Thread(() -> { for (int i = 1; i <= 4; i++) { threadTest.addA(); } }); t2 = new Thread(() -> { for (int i = 1; i <= 4; i++) { threadTest.addB(); } }); t3 = new Thread(() -> { for (int i = 1; i <= 4; i++) { threadTest.addC(); } }); //把Thread添加到集合 threadList.add(t1); threadList.add(t2); threadList.add(t3); //启动线程 t1.start(); t2.start(); t3.start(); for(Thread item : threadList){ try { //等待子线程执行后才执行主线程 item.join(); } catch (InterruptedException e) { e.printStackTrace(); } } List<Integer> integers = threadTest.getList(); Object[] array = integers.toArray(); System.out.println(Arrays.toString(array)); } }
-
JAVA多线程练习题答案。
2011-04-13 23:10:08JAVA多线程练习题的答案。都是一些基本的练习题。对初学者有帮助 -
java基础多线程练习题(1)
2017-08-08 15:26:15java基础之多线程的练习题,博客访问地址: http://blog.csdn.net/u014028392/article/details/76906801 -
多线程练习题java
2015-11-09 22:08:03java多线程初学者练习题目,供初学者练习使用 -
易语言-鱼刺多线程练习
2021-06-25 19:34:36鱼刺多线程练习源码。源码调用了鱼刺类_多线程应用.ec。 -
易语言-易语言多线程练习
2021-06-26 10:11:30多线程练习本期可能有点偏离但将的多线程是很有实质性的。 线程_启动 () 线程_挂起 () 线程_恢复 () 线程_销毁 () -
鱼刺多线程练习demo-易语言
2021-06-12 09:55:16鱼刺多线程练习demo -
多线程练习
2019-02-16 22:47:34写两个线程,一个线程打印1-52,另一个线程打印A-Z,打印顺序为12A34B…5152Z //写两个线程,一个线程打印1-52,另一个线程打印A-Z,打印顺序为12A34B...5152Z class Print { private Integer num=1; private Integer...写两个线程,一个线程打印1-52,另一个线程打印A-Z,打印顺序为12A34B…5152Z
//写两个线程,一个线程打印1-52,另一个线程打印A-Z,打印顺序为12A34B...5152Z class Print { private Integer num=1; private Integer flag=1; synchronized public void printNum() { while(num<27) { if(flag!=1) { try { wait(); //等待打印字母 } catch (InterruptedException e) { e.printStackTrace(); } } //打印数字 if(num<27) //加判断是因为最后一次num=26,数字线程等待字母线程,当字母打印结束, // num=27,会唤醒数字线程,那么数字线程将会以num=27继续执行 { System.out.print(num*2-1); System.out.print(num*2); flag=2; notify();//唤醒打印字母的线程 } } } synchronized public void printLetter() { while(num<27) { if(flag!=2) { try { wait(); //此时应该打印数字。等待 } catch (InterruptedException e) { e.printStackTrace(); } } //打印字母 System.out.print((char)(num-1+'A')); num++; flag=1; notify(); //唤醒打印字母的线程 } } } public class Print1A { public static void main(String[] args) { Print print=new Print(); Thread numThread=new Thread(new Runnable() { @Override public void run() { print.printNum(); } }); Thread letterThread=new Thread(new Runnable() { @Override public void run() { print.printLetter(); } }); numThread.start(); letterThread.start(); } }
12A34B56C78D910E1112F1314G1516H1718I1920J2122K2324L2526M2728N2930O3132P3334Q3536R3738S3940T4142U4344V4546W4748X4950Y5152Z
编写一个程序,启动三个线程,三个线程的名称分别是A,B,C;
// 每个线程将自己的名字在屏幕上打印5遍,打印顺序是
//ABCABCABCABCABC//编写一个程序,启动三个线程,三个线程的名称分别是A,B,C; // 每个线程将自己的名字在屏幕上打印5遍,打印顺序是 //ABCABCABCABCABC class PrintABCI { private Integer flag=1; private Integer count=1; //打印次数 public synchronized void printA() { while(flag!=1 ) { try { wait(); //等待打印B或C } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print('A'); flag=2; notifyAll(); } public synchronized void printB() { while(flag!=2 ) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print('B'); flag=3; notifyAll(); } public synchronized void printC() { while(flag!=3) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.print('C'); count++; flag=1; notifyAll(); } } public class PrintABC { public static void main(String[] args) { PrintABCI print=new PrintABCI(); new Thread(new Runnable() { @Override public void run() { for(int i=0;i<5;i++) print.printA(); } }).start(); new Thread((new Runnable() { @Override public void run() { for(int i=0;i<5;i++) print.printB(); } })).start(); new Thread(new Runnable() { @Override public void run() { for(int i=0;i<5;i++) print.printC(); } }).start(); } }
-
多线程练习-易语言
2021-06-12 16:11:53多线程练习 -
C++ 多线程练习题 以及知识点
2021-12-22 22:25:17转载:一些c++多线程习题 - geloutingyu - 博客园 (cnblogs.com) 知识点: this_thread::yield(); //当前线程放弃执行,操作系统调度另一线程继续执行 自己手写练习才有感觉: 第一题:子线程循环10次,接着主线...转载:一些c++多线程习题 - geloutingyu - 博客园 (cnblogs.com)
知识点:
this_thread::yield(); //当前线程放弃执行,操作系统调度另一线程继续执行
ifstream in(fileName); //ifstream 是针对文件读取的流
ofstream out(fileName, ios::app); //ofstream 是针对文件写入的流文件流对象有两个可用于随机文件访问的成员函数:tellp 和 tellg
tellp 用于返回写入位置,tellg 则用于返回读取位置自己手写练习才有感觉:
第一题:子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码
方法一:采用this_thread::yield();
#include <thread> #include <mutex> using namespace std; const int countNum = 50; int flag = 100; mutex mu; void fun(int num,string_view str) { for (int i=0;i< countNum;++i) { while (num != flag) { this_thread::yield(); //当前线程放弃执行,操作系统调度另一线程继续执行 } lock_guard<mutex> lock(mu); for (int j=0;j<flag;++j) { cout << str << ":" << j << endl; } flag = (flag == 10 ? 100 : 10); } } int main() { thread A(fun, 10, "child"); fun(100, "father"); A.join(); return 0; }
总结:fun(100, "father");要放在join之间,子线程A先于函数执行前创建了,主要是要让主线程先跑起来,this_thread::yield();使当前线程停止,让另外线程启动。
方法二:采用条件变量condition_variable
#include <mutex> #include <condition_variable> using namespace std; const int countNum = 50; int flag = 10; condition_variable cv; mutex mu; void fun(int num,string_view str) { for (int i=0;i< countNum;++i) { unique_lock<mutex> lock(mu); cv.wait(lock, [&]{return num == flag; }); for (int j=0;j<flag;++j) { cout << str << ":" << j << endl; } flag = (flag == 10 ? 100 : 10); cv.notify_one();//唤醒被锁住的线程 } } int main() { thread A(fun, 10, "child"); fun(100, "father"); A.join(); return 0; }
总结:condition_variable 只能和unique_lock搭配使用,原因可以看C++11:为什么 std::condition_variable 使用 std::unique_lock? - IT工具网 (coder.work)。
第二题:编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推
方法一:采用this_thread::yield();
方法二:采用条件变量condition_variable
总结:注意cv.wait 中填写的条件是 如果为真则执行接下来的代码。
第三题:(google笔试题):有四个线程1、2、3、4。线程 1 的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A:1 2 3 4 1 2....
B:2 3 4 1 2 3....
C:3 4 1 2 3 4....
D:4 1 2 3 4 1....
#include <thread> #include <mutex> #include <condition_variable> #include <fstream> using namespace std; mutex mu; condition_variable cv; const string fileName = "D://vsTest//BeStrong//txt//strong_"; ofstream f0(fileName+"A.txt"); ofstream f1(fileName + "B.txt"); ofstream f2(fileName + "C.txt"); ofstream f3(fileName + "D.txt"); ofstream* file[4]; int v[] = {4,1,2,3}; int a =0, b = 0, c = 0, d = 0; void fun(int x,int num) { while (num--) { for (int i=0;i<4;i++) { unique_lock<mutex> lock(mu); if (x==1) { cv.wait(lock, [&] { return v[i] == 4; }); (*file[i]) << 1; v[i] = 1; a++; lock.unlock(); cv.notify_all(); } else if (x == 2) { cv.wait(lock, [&] { return v[i] == 1; }); (*file[i]) << 2; v[i] = 2; b++; lock.unlock(); cv.notify_all(); } else if (x == 3) { cv.wait(lock, [&] { return v[i] == 2; }); (*file[i]) << 3; v[i] = 3; c++; lock.unlock(); cv.notify_all(); } else { cv.wait(lock, [&] { return v[i] == 3; }); (*file[i]) << 4; v[i] = 4; d++; lock.unlock(); cv.notify_all(); } } } } int main() { file[0] = &f0; file[1] = &f1; file[2] = &f2; file[3] = &f3; thread t0(fun,1,10); thread t1(fun, 2, 10); thread t2(fun, 3, 10); fun(4,10); t0.join(); t1.join(); t2.join(); for (size_t i = 0; i < 4; i++) { file[i]->close(); } return 0; }
总结:我在每个线程中放了一个变量,原本以为每个变量应该是只差1,查看结果如图,说明线程并不是顺序执行的,即使用条件变量,这本来就是线程的特点,随机性。但结果是顺序。这就是多线程并发的优势。
第四题:有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者读时写者也不能写
#include <thread> #include <mutex> #include <condition_variable> #include <fstream> using namespace std; mutex mu; condition_variable cv; const string fileName = "D://vsTest//BeStrong//txt//strong_A.txt"; ifstream in(fileName); //ifstream 是针对文件读取的流 ofstream out(fileName, ios::app); //ofstream 是针对文件写入的流 int cnt = 0; void write() { char ch; while (true) { unique_lock<mutex> lock(mu); ch = getchar(); out << ch; ++cnt; lock.unlock(); cv.notify_all(); } } void read() { char ch; while (true) { unique_lock<mutex> lock(mu); cv.wait(lock, [&] { return cnt>0; }); in >> ch; cout << "cout:" << ch << endl; --cnt; } } int main() { cnt = in.tellg();//文件流对象有两个可用于随机文件访问的成员函数:tellp 和 tellg //tellp 用于返回写入位置,tellg 则用于返回读取位置 thread w(write); thread r0(read); thread r1(read); thread r2(read); w.join(); r0.join(); r1.join(); r2.join(); in.close(); out.close(); return 0; }
第四题:STL 中的 queue 是非线程安全的,一个组合操作:front(); pop() 先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的 queue 的接口
#include <thread> #include <mutex> #include <condition_variable> #include <fstream> #include <queue> using namespace std; template<typename T> class thread_safe_queue { private: mutex mu; condition_variable cv; queue<T> que; public: thread_safe_queue() = default; ~thread_safe_queue() = default; thread_safe_queue(const queue<T>& q) :que(q) {} thread_safe_queue(const thread_safe_queue& tsq){ std::unique_lock<mutex> lock(mu); que = tsq; } void push(const T &data) { std::unique_lock<mutex> lock(mu); que.push(data); cout << "push:" << data << endl; lock.unlock(); cv.notify_all(); } T pop(void) { std::unique_lock<mutex> lock(mu); cv.wait(lock, [&] {return !que.empty(); }); T value = que.front(); que.pop(); return value; } bool empty(void) { std::unique_lock<mutex> lock(mu); return que.empty(); } }; thread_safe_queue<int> q; mutex mu; int main() { auto push_value = [&] { for (int i=0;i<100;++i) { q.push(i); std::this_thread::sleep_for(std::chrono::milliseconds(1)); //this_thread::yield(); //降低cpu使用率,死循环cpu占用很高的 } }; auto pop_value = [&] { while (true) { while (!q.empty()) { std::unique_lock<mutex> lock(mu); cout <<"pop:"<< q.pop() << endl; } } }; thread pushT(push_value); thread popT0(pop_value); thread popT1(pop_value); pushT.join(); popT0.join(); popT1.join(); return 0; }
总结:
通常来说使用sleep。
std::this_thread::sleep_for(std::chrono::milliseconds(1));
this_thread::yield(); //降低cpu使用率,死循环cpu占用很高的两种效果不一样:
-
多线程练习题目.doc
2021-09-28 11:04:41多线程练习题目.doc -
多线程练习题卷.pdf
2021-10-24 03:58:06多线程练习题卷.pdf -
多线程练习源码-易语言
2021-06-12 20:27:00多线程练习源码 -
头歌Educoder——Java高级特性 - 多线程练习题
2021-03-24 21:26:46本关任务:利用多线程相关知识控制三个线程,依照先后顺序顺序输出。 相关知识(略) 编程要求 请仔细阅读右侧代码,在 Begin-End 区域内进行代码补充,使线程依照先后顺序依次输出JavaThread+线程名。 提示:我们... -
Java多线程练习题
2008-11-21 09:00:27这是对Java多线程的一些相关练习题 包括选择 填空 简答 编程等题型 -
多线程练习题
2019-05-14 15:28:32多线程练习题 1.写一段简单的程序,启动两个线程交替打印1–100 题目分析: 只打印1—100,为了保证数据的同步必须加锁,同时又需要线程交替打印,则需要线程间的通信。 解题思想: 启动两个线程A和线程B,两个... -
Socket多线程练习
2019-03-16 01:09:57NULL 博文链接:https://lucane.iteye.com/blog/379796 -
Java多线程练习题.docx
2020-04-05 11:13:51Java多线程习题 一选择题 什么原因可导致线程停止执行( ) 线程调用了wait)方法 线程调用了yield)方法 线程调用了pause)方法 线程调用了sleep)方法 哪个方法是实现Runnable接口所需的( ) A. wait) Brun) Cstop) D... -
python 多线程练习题---四个线程同步打印a b c d
2020-12-11 09:09:32python 多线程练习题---四个线程同步打印a b c d1. 题目描述有四个线程,每个线程只打印一个字符,这四个字符分别是 a b c d ,现在要求你做到四个线程顺序打印 a b c d ,且每个线程都打印10次2. 思路分析假设1 线程... -
Java高级特性 - 多线程练习题
2021-01-17 11:29:53本关任务:利用多线程相关知识控制三个线程,依照先后顺序顺序输出。 相关知识(略) 编程要求 请仔细阅读右侧代码,在 Begin-End 区域内进行代码补充,使线程依照先后顺序依次输出JavaThread+线程名。 提示:我们... -
pthread_piano-DE1-SOC:合成钢琴上的中间C范围作为多线程练习
2021-02-13 08:14:02pthread_piano-DE1-SOC 在钢琴上将中级C范围合成为多线程并与音频CODEC练习一起使用。 该程序有两个线程,一个线程侦听键盘输入以模拟钢琴键,另一个线程从按下的键计算样本。 tone_volume是互斥变量,并使用衰减...